Blame view

RIOT/sys/net/network_layer/ipv6/addr/ipv6_addr.c 3.55 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  /*
   * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
   *
   * This file is subject to the terms and conditions of the GNU Lesser General
   * Public License v2.1. See the file LICENSE in the top level directory for
   * more details.
   */
  
  /**
   * @{
   *
   * @file
   *
   * @author      Martine Lenders <mlenders@inf.fu-berlin.de>
   */
  
  #include <assert.h>
  #include <stdlib.h>
  #include <string.h>
  
  #include "net/ipv6/addr.h"
  
  #ifdef MODULE_FMT
  #include "fmt.h"
  #else
  #include <stdio.h>
  #endif
  
  const ipv6_addr_t ipv6_addr_unspecified = IPV6_ADDR_UNSPECIFIED;
  const ipv6_addr_t ipv6_addr_loopback = IPV6_ADDR_LOOPBACK;
  const ipv6_addr_t ipv6_addr_link_local_prefix = IPV6_ADDR_LINK_LOCAL_PREFIX;
  const ipv6_addr_t ipv6_addr_solicited_node_prefix = IPV6_ADDR_SOLICITED_NODE_PREFIX;
  const ipv6_addr_t ipv6_addr_all_nodes_if_local = IPV6_ADDR_ALL_NODES_IF_LOCAL;
  const ipv6_addr_t ipv6_addr_all_nodes_link_local = IPV6_ADDR_ALL_NODES_LINK_LOCAL;
  const ipv6_addr_t ipv6_addr_all_routers_if_local = IPV6_ADDR_ALL_ROUTERS_IF_LOCAL;
  const ipv6_addr_t ipv6_addr_all_routers_link_local = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL;
  const ipv6_addr_t ipv6_addr_all_routers_site_local = IPV6_ADDR_ALL_ROUTERS_SITE_LOCAL;
  
  bool ipv6_addr_equal(const ipv6_addr_t *a, const ipv6_addr_t *b)
  {
      return (a->u64[0].u64 == b->u64[0].u64) &&
             (a->u64[1].u64 == b->u64[1].u64);
  }
  
  uint8_t ipv6_addr_match_prefix(const ipv6_addr_t *a, const ipv6_addr_t *b)
  {
      uint8_t prefix_len = 0;
  
      if ((a == NULL) || (b == NULL)) {
          return 0;
      }
  
      if (a == b) {
          return 128;
      }
  
      for (int i = 0; i < 16; i++) {
          /* if bytes are equal add 8 */
          if (a->u8[i] == b->u8[i]) {
              prefix_len += 8;
          }
          else {
              uint8_t xor = (a->u8[i] ^ b->u8[i]);
  
              /* while bits from byte equal add 1 */
              for (int j = 0; j < 8; j++) {
                  if ((xor & 0x80) == 0) {
                      prefix_len++;
                      xor = xor << 1;
                  }
                  else {
                      break;
                  }
              }
  
              break;
          }
      }
  
      return prefix_len;
  }
  
  void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix,
                             uint8_t bits)
  {
      uint8_t bytes;
  
      if (bits > 128) {
          bits = 128;
      }
  
      bytes = bits / 8;
  
      memcpy(out, prefix, bytes);
  
      if (bits % 8) {
          uint8_t mask = 0xff << (8 - (bits - (bytes * 8)));
  
          out->u8[bytes] &= ~mask;
          out->u8[bytes] |= (prefix->u8[bytes] & mask);
      }
  }
  
  void ipv6_addr_init_iid(ipv6_addr_t *out, const uint8_t *iid, uint8_t bits)
  {
      uint8_t unaligned_bits, bytes, pos;
  
      if (bits > 128) {
          bits = 128;
      }
  
      unaligned_bits = bits % 8;
      bytes = bits / 8;
      pos = (IPV6_ADDR_BIT_LEN / 8) - bytes;
  
      if (unaligned_bits) {
          uint8_t mask = 0xff << unaligned_bits;
          out->u8[pos - 1] &= mask;
          out->u8[pos - 1] |= (*iid & ~mask);
          iid++;
      }
  
      memcpy(&(out->u8[pos]), iid, bytes);
  }
  
  int ipv6_addr_split(char *addr_str, char seperator, int _default)
  {
      char *sep = addr_str;
      while(*++sep) {
          if (*sep == seperator) {
              *sep++ = '\0';
              if (*sep) {
                  _default = atoi(sep);
              }
              break;
          }
      }
  
      return _default;
  }
  
  void ipv6_addr_print(const ipv6_addr_t *addr)
  {
      assert(addr);
      char addr_str[IPV6_ADDR_MAX_STR_LEN];
      ipv6_addr_to_str(addr_str, addr, sizeof(addr_str));
  #ifdef MODULE_FMT
      print_str(addr_str);
  #else
      printf("%s", addr_str);
  #endif
  }
  
  /**
   * @}
   */