The friendly Operating System for the Internet of Things
ipv6/addr.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
3  *
4  * This file is subject to the terms and conditions of the GNU Lesser General
5  * Public License v2.1. See the file LICENSE in the top level directory for
6  * more details.
7  */
8 
27 #ifndef IPV6_ADDR_H
28 #define IPV6_ADDR_H
29 
30 #include <stdbool.h>
31 #include <string.h>
32 
33 #include "byteorder.h"
34 #include "net/ipv4/addr.h"
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
43 #define IPV6_ADDR_BIT_LEN (128)
44 
45 #ifdef MODULE_IPV4_ADDR
46 
49 #define IPV6_ADDR_MAX_STR_LEN (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"))
50 #else
51 
54 #define IPV6_ADDR_MAX_STR_LEN (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))
55 #endif
56 
57 
69 #define IPV6_ADDR_SITE_LOCAL_PREFIX (0xfec0)
70 
74 typedef union {
75  uint8_t u8[16];
79 } ipv6_addr_t;
80 
88 #define IPV6_ADDR_UNSPECIFIED {{ 0x00, 0x00, 0x00, 0x00, \
89  0x00, 0x00, 0x00, 0x00, \
90  0x00, 0x00, 0x00, 0x00, \
91  0x00, 0x00, 0x00, 0x00 }}
92 
100 #define IPV6_ADDR_LOOPBACK {{ 0x00, 0x00, 0x00, 0x00, \
101  0x00, 0x00, 0x00, 0x00, \
102  0x00, 0x00, 0x00, 0x00, \
103  0x00, 0x00, 0x00, 0x01 }}
104 
111 #define IPV6_ADDR_LINK_LOCAL_PREFIX {{ 0xfe, 0x80, 0x00, 0x00, \
112  0x00, 0x00, 0x00, 0x00, \
113  0x00, 0x00, 0x00, 0x00, \
114  0x00, 0x00, 0x00, 0x00 }}
115 
124 #define IPV6_ADDR_ALL_NODES_IF_LOCAL {{ 0xff, 0x01, 0x00, 0x00, \
125  0x00, 0x00, 0x00, 0x00, \
126  0x00, 0x00, 0x00, 0x00, \
127  0x00, 0x00, 0x00, 0x01 }}
128 
137 #define IPV6_ADDR_ALL_NODES_LINK_LOCAL {{ 0xff, 0x02, 0x00, 0x00, \
138  0x00, 0x00, 0x00, 0x00, \
139  0x00, 0x00, 0x00, 0x00, \
140  0x00, 0x00, 0x00, 0x01 }}
141 
150 #define IPV6_ADDR_ALL_ROUTERS_IF_LOCAL {{ 0xff, 0x01, 0x00, 0x00, \
151  0x00, 0x00, 0x00, 0x00, \
152  0x00, 0x00, 0x00, 0x00, \
153  0x00, 0x00, 0x00, 0x02 }}
154 
163 #define IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL {{ 0xff, 0x02, 0x00, 0x00, \
164  0x00, 0x00, 0x00, 0x00, \
165  0x00, 0x00, 0x00, 0x00, \
166  0x00, 0x00, 0x00, 0x02 }}
167 
168 
177 #define IPV6_ADDR_ALL_ROUTERS_SITE_LOCAL {{ 0xff, 0x05, 0x00, 0x00, \
178  0x00, 0x00, 0x00, 0x00, \
179  0x00, 0x00, 0x00, 0x00, \
180  0x00, 0x00, 0x00, 0x02 }}
181 
190 #define IPV6_ADDR_SOLICITED_NODE_PREFIX {{ 0xff, 0x02, 0x00, 0x00, \
191  0x00, 0x00, 0x00, 0x00, \
192  0x00, 0x00, 0x00, 0x01, \
193  0xff, 0x00, 0x00, 0x00 }}
194 
208 #define IPV6_ADDR_MCAST_FLAG_TRANSIENT (0x01)
209 
217 #define IPV6_ADDR_MCAST_FLAG_PREFIX_BASED (0x02)
218 
226 #define IPV6_ADDR_MCAST_FLAG_EMBED_ON_RP (0x04)
227 
238 #define IPV6_ADDR_MCAST_SCP_IF_LOCAL (0x1)
239 #define IPV6_ADDR_MCAST_SCP_LINK_LOCAL (0x2)
251 #define IPV6_ADDR_MCAST_SCP_REALM_LOCAL (0x3)
252 #define IPV6_ADDR_MCAST_SCP_ADMIN_LOCAL (0x4)
253 #define IPV6_ADDR_MCAST_SCP_SITE_LOCAL (0x5)
254 #define IPV6_ADDR_MCAST_SCP_ORG_LOCAL (0x8)
255 #define IPV6_ADDR_MCAST_SCP_GLOBAL (0xe)
265 extern const ipv6_addr_t ipv6_addr_unspecified;
266 
270 extern const ipv6_addr_t ipv6_addr_loopback;
271 
276 
281 
286 
291 
296 
301 
322 static inline bool ipv6_addr_is_unspecified(const ipv6_addr_t *addr)
323 {
324  return (memcmp(addr, &ipv6_addr_unspecified, sizeof(ipv6_addr_t)) == 0);
325 }
326 
339 static inline bool ipv6_addr_is_loopback(const ipv6_addr_t *addr)
340 {
341  return (memcmp(addr, &ipv6_addr_loopback, sizeof(ipv6_addr_t)) == 0);
342 }
343 
356 static inline bool ipv6_addr_is_ipv4_compat(const ipv6_addr_t *addr)
357 {
358  return (memcmp(addr, &ipv6_addr_unspecified,
359  sizeof(ipv6_addr_t) - sizeof(ipv4_addr_t)) == 0);
360 }
361 
374 static inline bool ipv6_addr_is_ipv4_mapped(const ipv6_addr_t *addr)
375 {
376  return ((memcmp(addr, &ipv6_addr_unspecified,
377  sizeof(ipv6_addr_t) - sizeof(ipv4_addr_t) - 2) == 0) &&
378  (addr->u16[5].u16 == 0xffff));
379 }
380 
393 static inline bool ipv6_addr_is_multicast(const ipv6_addr_t *addr)
394 {
395  return (addr->u8[0] == 0xff);
396 }
397 
413 static inline bool ipv6_addr_is_link_local(const ipv6_addr_t *addr)
414 {
415  return (memcmp(addr, &ipv6_addr_link_local_prefix, sizeof(addr->u64[0])) == 0) ||
416  (ipv6_addr_is_multicast(addr) &&
417  (addr->u8[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_LINK_LOCAL);
418 }
419 
436 static inline bool ipv6_addr_is_site_local(const ipv6_addr_t *addr)
437 {
438  return (((byteorder_ntohs(addr->u16[0]) & 0xffc0) ==
440  (ipv6_addr_is_multicast(addr) &&
441  (addr->u8[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_SITE_LOCAL));
442 }
443 
456 static inline bool ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr)
457 {
458  return ((addr->u8[0] == 0xfc) || (addr->u8[0] == 0xfd));
459 }
460 
473 static inline bool ipv6_addr_is_global(const ipv6_addr_t *addr)
474 {
475  /* first check for multicast with global scope */
476  if (ipv6_addr_is_multicast(addr)) {
477  return ((addr->u8[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_GLOBAL);
478  }
479  else {
480  return !(ipv6_addr_is_link_local(addr) ||
481  ipv6_addr_is_unspecified(addr) ||
482  ipv6_addr_is_loopback(addr));
483  }
484 }
485 
486 
499 static inline bool ipv6_addr_is_solicited_node(const ipv6_addr_t *addr)
500 {
501  return (memcmp(addr, &ipv6_addr_solicited_node_prefix,
502  sizeof(ipv6_addr_t) - 3) == 0);
503 }
504 
505 
515 bool ipv6_addr_equal(const ipv6_addr_t *a, const ipv6_addr_t *b);
516 
526 uint8_t ipv6_addr_match_prefix(const ipv6_addr_t *a, const ipv6_addr_t *b);
527 
537 void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, uint8_t bits);
538 
548 void ipv6_addr_init_iid(ipv6_addr_t *out, const uint8_t *iid, uint8_t bits);
549 
559 static inline void ipv6_addr_set_unspecified(ipv6_addr_t *addr)
560 {
561  memset(addr, 0, sizeof(ipv6_addr_t));
562 }
563 
573 static inline void ipv6_addr_set_loopback(ipv6_addr_t *addr)
574 {
575  memset(addr, 0, sizeof(ipv6_addr_t));
576  addr->u8[15] = 1;
577 }
578 
589 {
590  memcpy(addr, &ipv6_addr_link_local_prefix, sizeof(addr->u64[0]));
591 }
592 
604 static inline void ipv6_addr_set_iid(ipv6_addr_t *addr, uint64_t iid)
605 {
606  addr->u64[1] = byteorder_htonll(iid);
607 }
608 
620 static inline void ipv6_addr_set_aiid(ipv6_addr_t *addr, uint8_t *iid)
621 {
622  memcpy(&addr->u64[1], iid, sizeof(addr->u64[1]));
623 }
624 
636 static inline void ipv6_addr_set_multicast(ipv6_addr_t *addr, unsigned int flags,
637  unsigned int scope)
638 {
639  addr->u8[0] = 0xff;
640  addr->u8[1] = (((uint8_t)flags) << 4) | (((uint8_t) scope) & 0x0f);
641 }
642 
654 static inline void ipv6_addr_set_all_nodes_multicast(ipv6_addr_t *addr, unsigned int scope)
655 {
656  memcpy(addr, &ipv6_addr_all_nodes_if_local, sizeof(ipv6_addr_t));
657  addr->u8[1] = (uint8_t)scope;
658 }
659 
671 static inline void ipv6_addr_set_all_routers_multicast(ipv6_addr_t *addr, unsigned int scope)
672 {
673  memcpy(addr, &ipv6_addr_all_routers_if_local, sizeof(ipv6_addr_t));
674  addr->u8[1] = (uint8_t)scope;
675 }
676 
688 static inline void ipv6_addr_set_solicited_nodes(ipv6_addr_t *out, const ipv6_addr_t *in)
689 {
690  out->u64[0] = byteorder_htonll(0xff02000000000000);
691  out->u32[2] = byteorder_htonl(1);
692  out->u8[12] = 0xff;
693  out->u8[13] = in->u8[13];
694  out->u16[7] = in->u16[7];
695 }
696 
713 char *ipv6_addr_to_str(char *result, const ipv6_addr_t *addr, uint8_t result_len);
714 
730 ipv6_addr_t *ipv6_addr_from_str(ipv6_addr_t *result, const char *addr);
731 
744 int ipv6_addr_split(char *addr_str, char seperator, int _default);
745 
754 static inline int ipv6_addr_split_prefix(char *addr_str)
755 {
756  return ipv6_addr_split(addr_str, '/', 128);
757 }
758 
767 static inline int ipv6_addr_split_iface(char *addr_str)
768 {
769  return ipv6_addr_split(addr_str, '%', -1);
770 }
771 
777 void ipv6_addr_print(const ipv6_addr_t *addr);
778 
779 #ifdef __cplusplus
780 }
781 #endif
782 
783 #endif /* IPV6_ADDR_H */
784 
uint8_t u8[16]
divided by 16 8-bit words.
Definition: ipv6/addr.h:75
static void ipv6_addr_set_aiid(ipv6_addr_t *addr, uint8_t *iid)
Sets the 64-bit interface ID (as array) of a unicast or anycast IPv6 address.
Definition: ipv6/addr.h:620
static bool ipv6_addr_is_link_local(const ipv6_addr_t *addr)
Check if addr is a link-local address.
Definition: ipv6/addr.h:413
IPv6 address type and helper functions definitions.
#define IPV6_ADDR_MCAST_SCP_GLOBAL
global scope
Definition: ipv6/addr.h:255
static void ipv6_addr_set_all_nodes_multicast(ipv6_addr_t *addr, unsigned int scope)
Sets addr dynamically to an all nodes multicast IPv6 address (ff0S::1, where S is the scope)...
Definition: ipv6/addr.h:654
const ipv6_addr_t ipv6_addr_all_routers_site_local
const ipv6_addr_t ipv6_addr_all_nodes_if_local
static bool ipv6_addr_is_ipv4_compat(const ipv6_addr_t *addr)
Checks if addr is a IPv4-compatible IPv6 address.
Definition: ipv6/addr.h:356
network_uint64_t u64[2]
divided by 2 64-bit words.
Definition: ipv6/addr.h:78
const ipv6_addr_t ipv6_addr_all_routers_link_local
A 32 bit integer in big endian aka network byte order.
Definition: byteorder.h:86
uint8_t ipv6_addr_match_prefix(const ipv6_addr_t *a, const ipv6_addr_t *b)
Checks up to which bit-count two IPv6 addresses match in their prefix.
const ipv6_addr_t ipv6_addr_loopback
network_uint16_t u16[8]
divided by 8 16-bit words.
Definition: ipv6/addr.h:76
A 16 bit integer in big endian aka network byte order.
Definition: byteorder.h:76
static bool ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr)
Check if addr is unique local unicast address.
Definition: ipv6/addr.h:456
static bool ipv6_addr_is_global(const ipv6_addr_t *addr)
Check if addr is global unicast address.
Definition: ipv6/addr.h:473
void ipv6_addr_init_iid(ipv6_addr_t *out, const uint8_t *iid, uint8_t bits)
Sets the last bits of IPv6 address out to iid.
static uint16_t byteorder_ntohs(network_uint16_t v)
Convert from network byte order to host byte order, 16 bit.
Definition: byteorder.h:373
static void ipv6_addr_set_multicast(ipv6_addr_t *addr, unsigned int flags, unsigned int scope)
Sets the bits for an address required to be a multicast address.
Definition: ipv6/addr.h:636
#define IPV6_ADDR_MCAST_SCP_LINK_LOCAL
link-local scope
Definition: ipv6/addr.h:239
const ipv6_addr_t ipv6_addr_all_routers_if_local
static bool ipv6_addr_is_loopback(const ipv6_addr_t *addr)
Checks if addr is a loopback address.
Definition: ipv6/addr.h:339
const ipv6_addr_t ipv6_addr_link_local_prefix
const ipv6_addr_t ipv6_addr_unspecified
In-memory constants of defined addresses and prefixes.
network_uint32_t u32[4]
divided by 4 32-bit words.
Definition: ipv6/addr.h:77
static void ipv6_addr_set_solicited_nodes(ipv6_addr_t *out, const ipv6_addr_t *in)
Set out to the solicited-node multicast address computed from in.
Definition: ipv6/addr.h:688
static int ipv6_addr_split_prefix(char *addr_str)
split IPv6 prefix string representation
Definition: ipv6/addr.h:754
static bool ipv6_addr_is_solicited_node(const ipv6_addr_t *addr)
Check if addr is solicited-node multicast address.
Definition: ipv6/addr.h:499
bool ipv6_addr_equal(const ipv6_addr_t *a, const ipv6_addr_t *b)
Checks if two IPv6 addresses are equal.
char * ipv6_addr_to_str(char *result, const ipv6_addr_t *addr, uint8_t result_len)
Converts an IPv6 address to its string representation.
static bool ipv6_addr_is_site_local(const ipv6_addr_t *addr)
Checks if addr is a site-local address.
Definition: ipv6/addr.h:436
const ipv6_addr_t ipv6_addr_all_nodes_link_local
uint16_t u16
16 bit representation
Definition: byteorder.h:77
#define IPV6_ADDR_MCAST_SCP_SITE_LOCAL
site-local scope
Definition: ipv6/addr.h:253
static int ipv6_addr_split_iface(char *addr_str)
split IPv6 address + interface specifier
Definition: ipv6/addr.h:767
static void ipv6_addr_set_loopback(ipv6_addr_t *addr)
Sets addr dynamically to the loopback IPv6 address (::1).
Definition: ipv6/addr.h:573
static bool ipv6_addr_is_ipv4_mapped(const ipv6_addr_t *addr)
Checks if addr is a IPv4-mapped IPv6 address.
Definition: ipv6/addr.h:374
static network_uint32_t byteorder_htonl(uint32_t v)
Convert from host byte order to network byte order, 32 bit.
Definition: byteorder.h:361
Functions to work with different byte orders.
static void ipv6_addr_set_link_local_prefix(ipv6_addr_t *addr)
Sets the first 64 bit of addr to link local prefix (fe08::/64).
Definition: ipv6/addr.h:588
Data type to represent an IPv4 address.
Definition: ipv4/addr.h:40
static void ipv6_addr_set_iid(ipv6_addr_t *addr, uint64_t iid)
Sets the 64-bit interface ID (as integer) of a unicast or anycast IPv6 address.
Definition: ipv6/addr.h:604
Data type to represent an IPv6 address.
Definition: ipv6/addr.h:74
static void ipv6_addr_set_all_routers_multicast(ipv6_addr_t *addr, unsigned int scope)
Sets addr dynamically to an all routers multicast IPv6 address (ff0S::2, where S is the scope)...
Definition: ipv6/addr.h:671
void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, uint8_t bits)
Sets IPv6 address out with the first bits taken from prefix and leaves the remaining bits untouched...
ipv6_addr_t * ipv6_addr_from_str(ipv6_addr_t *result, const char *addr)
Converts an IPv6 address string representation to a byte-represented IPv6 address.
static bool ipv6_addr_is_unspecified(const ipv6_addr_t *addr)
Checks if addr is unspecified (all zero).
Definition: ipv6/addr.h:322
void ipv6_addr_print(const ipv6_addr_t *addr)
Print IPv6 address to stdout.
A 64 bit integer in big endian aka network byte order.
Definition: byteorder.h:98
static bool ipv6_addr_is_multicast(const ipv6_addr_t *addr)
Check if addr is a multicast address.
Definition: ipv6/addr.h:393
static void ipv6_addr_set_unspecified(ipv6_addr_t *addr)
Sets addr dynamically to the unspecified IPv6 address (::).
Definition: ipv6/addr.h:559
#define IPV6_ADDR_SITE_LOCAL_PREFIX
The first 10 bits of a site-local IPv6 unicast address.
Definition: ipv6/addr.h:69
int ipv6_addr_split(char *addr_str, char seperator, int _default)
split IPv6 address string representation
const ipv6_addr_t ipv6_addr_solicited_node_prefix
static network_uint64_t byteorder_htonll(uint64_t v)
Convert from host byte order to network byte order, 64 bit.
Definition: byteorder.h:367