44 * \note Adapted from Jens Jakobsen implementation (chillispot). |
44 * \note Adapted from Jens Jakobsen implementation (chillispot). |
45 */ |
45 */ |
46 static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level) |
46 static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level) |
47 { |
47 { |
48 #define mix(a, b, c) \ |
48 #define mix(a, b, c) \ |
49 ({ \ |
49 ({ \ |
50 (a) -= (b); (a) -= (c); (a) ^= ((c) >> 13); \ |
50 (a) -= (b); (a) -= (c); (a) ^= ((c) >> 13); \ |
51 (b) -= (c); (b) -= (a); (b) ^= ((a) << 8); \ |
51 (b) -= (c); (b) -= (a); (b) ^= ((a) << 8); \ |
52 (c) -= (a); (c) -= (b); (c) ^= ((b) >> 13); \ |
52 (c) -= (a); (c) -= (b); (c) ^= ((b) >> 13); \ |
53 (a) -= (b); (a) -= (c); (a) ^= ((c) >> 12); \ |
53 (a) -= (b); (a) -= (c); (a) ^= ((c) >> 12); \ |
54 (b) -= (c); (b) -= (a); (b) ^= ((a) << 16); \ |
54 (b) -= (c); (b) -= (a); (b) ^= ((a) << 16); \ |
55 (c) -= (a); (c) -= (b); (c) ^= ((b) >> 5); \ |
55 (c) -= (a); (c) -= (b); (c) ^= ((b) >> 5); \ |
56 (a) -= (b); (a) -= (c); (a) ^= ((c) >> 3); \ |
56 (a) -= (b); (a) -= (c); (a) ^= ((c) >> 3); \ |
57 (b) -= (c); (b) -= (a); (b) ^= ((a) << 10); \ |
57 (b) -= (c); (b) -= (a); (b) ^= ((a) << 10); \ |
58 (c) -= (a); (c) -= (b); (c) ^= ((b) >> 15); \ |
58 (c) -= (a); (c) -= (b); (c) ^= ((b) >> 15); \ |
59 }) |
59 }) |
60 |
60 |
61 typedef uint32_t ub4; /* unsigned 4-byte quantities */ |
61 typedef uint32_t ub4; /* unsigned 4-byte quantities */ |
62 typedef unsigned char ub1; /* unsigned 1-byte quantities */ |
62 typedef unsigned char ub1; /* unsigned 1-byte quantities */ |
63 uint32_t a = 0; |
63 uint32_t a = 0; |
64 uint32_t b = 0; |
64 uint32_t b = 0; |
70 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ |
70 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ |
71 c = level; /* the previous hash value */ |
71 c = level; /* the previous hash value */ |
72 |
72 |
73 /* handle most of the key */ |
73 /* handle most of the key */ |
74 while (len >= 12) |
74 while (len >= 12) |
75 { |
75 { |
76 a += (k[0] + ((ub4)k[1] << 8) + ((ub4)k[2] << 16) + ((ub4)k[3] << 24)); |
76 a += (k[0] + ((ub4)k[1] << 8) + ((ub4)k[2] << 16) + ((ub4)k[3] << 24)); |
77 b += (k[4] + ((ub4)k[5] << 8) + ((ub4)k[6] << 16) + ((ub4)k[7] << 24)); |
77 b += (k[4] + ((ub4)k[5] << 8) + ((ub4)k[6] << 16) + ((ub4)k[7] << 24)); |
78 c += (k[8] + ((ub4)k[9] << 8) + ((ub4)k[10] << 16) + ((ub4)k[11] << 24)); |
78 c += (k[8] + ((ub4)k[9] << 8) + ((ub4)k[10] << 16) + ((ub4)k[11] << 24)); |
79 mix (a, b, c); |
79 mix (a, b, c); |
80 k += 12; |
80 k += 12; |
81 len -= 12; |
81 len -= 12; |
82 } |
82 } |
83 |
83 |
84 /* handle the last 11 bytes */ |
84 /* handle the last 11 bytes */ |
85 c += length; |
85 c += length; |
86 switch (len) /* all the case statements fall through */ |
86 switch (len) /* all the case statements fall through */ |
87 { |
87 { |
88 case 11: c += ((ub4)k[10] << 24); |
88 case 11: c += ((ub4)k[10] << 24); |
89 case 10: c += ((ub4)k[9] << 16); |
89 case 10: c += ((ub4)k[9] << 16); |
90 case 9 : c += ((ub4)k[8] << 8); /* the first byte of c is reserved for the length */ |
90 case 9 : c += ((ub4)k[8] << 8); /* the first byte of c is reserved for the length */ |
91 case 8 : b += ((ub4)k[7] << 24); |
91 case 8 : b += ((ub4)k[7] << 24); |
92 case 7 : b += ((ub4)k[6] << 16); |
92 case 7 : b += ((ub4)k[6] << 16); |
133 memset (tp, 0x00, 16); |
133 memset (tp, 0x00, 16); |
134 endp = tp + 16; |
134 endp = tp + 16; |
135 |
135 |
136 /* Leading :: requires some special handling. */ |
136 /* Leading :: requires some special handling. */ |
137 if (*address == ':') |
137 if (*address == ':') |
138 { |
138 { |
139 if (*++address != ':') |
139 if (*++address != ':') |
140 { |
140 { |
|
141 return (0); |
|
142 } |
|
143 } |
|
144 curtok = address; |
|
145 |
|
146 while ((ch = *address++) != '\0') |
|
147 { |
|
148 const char *pch = 0; |
|
149 |
|
150 if ((pch = strchr ((xdigits = xdigits_l), ch)) == 0) |
|
151 { |
|
152 pch = strchr ((xdigits = xdigits_u), ch); |
|
153 } |
|
154 |
|
155 if (pch != 0) |
|
156 { |
|
157 val <<= 4; |
|
158 val |= (pch - xdigits); |
|
159 |
|
160 if (++seen_xdigits > 4) |
|
161 { |
|
162 return (0); |
|
163 } |
|
164 continue; |
|
165 } |
|
166 if (ch == ':') |
|
167 { |
|
168 curtok = address; |
|
169 |
|
170 if (!seen_xdigits) |
|
171 { |
|
172 if (colonp) |
|
173 return (0); |
|
174 colonp = tp; |
|
175 continue; |
|
176 } |
|
177 |
|
178 if (tp + 2 > endp) |
|
179 { |
|
180 return (0); |
|
181 } |
|
182 |
|
183 *tp++ = (unsigned char) (val >> 8) & 0xff; |
|
184 *tp++ = (unsigned char) val & 0xff; |
|
185 seen_xdigits = 0; |
|
186 val = 0; |
|
187 continue; |
|
188 } |
|
189 |
|
190 /* TODO Handle IPv4 mapped address (2001::192.168.0.1) */ |
|
191 #if 0 |
|
192 if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) && |
|
193 inet_pton4(curtok, tp) > 0) |
|
194 { |
|
195 tp += 4 /*NS_INADDRSZ*/; |
|
196 seen_xdigits = 0; |
|
197 break;/* '\0' was seen by inet_pton4(). */ |
|
198 } |
|
199 #endif |
141 return (0); |
200 return (0); |
142 } |
201 } |
143 } |
202 |
144 curtok = address; |
203 if (seen_xdigits) |
145 |
204 { |
146 while ((ch = *address++) != '\0') |
205 if (tp + 2 > endp) |
147 { |
206 { |
148 const char *pch = 0; |
|
149 |
|
150 if ((pch = strchr ((xdigits = xdigits_l), ch)) == 0) |
|
151 { |
|
152 pch = strchr ((xdigits = xdigits_u), ch); |
|
153 } |
|
154 |
|
155 if (pch != 0) |
|
156 { |
|
157 val <<= 4; |
|
158 val |= (pch - xdigits); |
|
159 |
|
160 if (++seen_xdigits > 4) |
|
161 { |
|
162 return (0); |
|
163 } |
|
164 continue; |
|
165 } |
|
166 if (ch == ':') |
|
167 { |
|
168 curtok = address; |
|
169 |
|
170 if (!seen_xdigits) |
|
171 { |
|
172 if (colonp) |
|
173 return (0); |
207 return (0); |
174 colonp = tp; |
208 } |
175 continue; |
|
176 } |
|
177 |
|
178 if (tp + 2 > endp) |
|
179 { |
|
180 return (0); |
|
181 } |
|
182 |
|
183 *tp++ = (unsigned char) (val >> 8) & 0xff; |
209 *tp++ = (unsigned char) (val >> 8) & 0xff; |
184 *tp++ = (unsigned char) val & 0xff; |
210 *tp++ = (unsigned char) val & 0xff; |
185 seen_xdigits = 0; |
211 } |
186 val = 0; |
212 |
187 continue; |
213 if (colonp != 0) |
188 } |
214 { |
189 |
215 /* |
190 /* TODO Handle IPv4 mapped address (2001::192.168.0.1) */ |
216 * Since some memmove ()'s erroneously fail to handle |
191 #if 0 |
217 * overlapping regions, we'll do the shift by hand. |
192 if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) && |
218 */ |
193 inet_pton4(curtok, tp) > 0) |
219 const int n = tp - colonp; |
194 { |
220 int i = 0; |
195 tp += 4 /*NS_INADDRSZ*/; |
221 |
196 seen_xdigits = 0; |
222 if (tp == endp) |
197 break;/* '\0' was seen by inet_pton4(). */ |
223 { |
198 } |
224 return (0); |
199 #endif |
225 } |
200 return (0); |
226 |
201 } |
227 for (i = 1; i <= n; i++) |
202 |
228 { |
203 if (seen_xdigits) |
229 endp[- i] = colonp[n - i]; |
204 { |
230 colonp[n - i] = 0; |
205 if (tp + 2 > endp) |
231 } |
|
232 |
|
233 tp = endp; |
|
234 } |
|
235 |
|
236 if (tp != endp) |
206 { |
237 { |
207 return (0); |
238 return (0); |
208 } |
239 } |
209 *tp++ = (unsigned char) (val >> 8) & 0xff; |
|
210 *tp++ = (unsigned char) val & 0xff; |
|
211 } |
|
212 |
|
213 if (colonp != 0) |
|
214 { |
|
215 /* |
|
216 * Since some memmove ()'s erroneously fail to handle |
|
217 * overlapping regions, we'll do the shift by hand. |
|
218 */ |
|
219 const int n = tp - colonp; |
|
220 int i = 0; |
|
221 |
|
222 if (tp == endp) |
|
223 { |
|
224 return (0); |
|
225 } |
|
226 |
|
227 for (i = 1; i <= n; i++) |
|
228 { |
|
229 endp[- i] = colonp[n - i]; |
|
230 colonp[n - i] = 0; |
|
231 } |
|
232 |
|
233 tp = endp; |
|
234 } |
|
235 |
|
236 if (tp != endp) |
|
237 { |
|
238 return (0); |
|
239 } |
|
240 |
240 |
241 memcpy (addr, tmp, 16); |
241 memcpy (addr, tmp, 16); |
242 return (1); |
242 return (1); |
243 } |
243 } |
244 |
244 |
402 memcpy (addr, m_address, 16); |
402 memcpy (addr, m_address, 16); |
403 ((Ipv6Prefix)prefix).GetBytes (pref); |
403 ((Ipv6Prefix)prefix).GetBytes (pref); |
404 |
404 |
405 /* a little bit ugly... */ |
405 /* a little bit ugly... */ |
406 for (i = 0 ; i < 16 ; i++) |
406 for (i = 0 ; i < 16 ; i++) |
407 { |
407 { |
408 addr[i] = addr[i] & pref[i]; |
408 addr[i] = addr[i] & pref[i]; |
409 } |
409 } |
410 ipv6.Set (addr); |
410 ipv6.Set (addr); |
411 return ipv6; |
411 return ipv6; |
412 } |
412 } |
413 |
413 |
414 bool Ipv6Address::IsSolicitedMulticast () const |
414 bool Ipv6Address::IsSolicitedMulticast () const |
531 |
531 |
532 bool Ipv6Address::IsLinkLocal () const |
532 bool Ipv6Address::IsLinkLocal () const |
533 { |
533 { |
534 Ipv6Address linkLocal ("fe80::0"); |
534 Ipv6Address linkLocal ("fe80::0"); |
535 if (!IsMulticast () && ((Ipv6Address*)this)->CombinePrefix (Ipv6Prefix (64)) == linkLocal) |
535 if (!IsMulticast () && ((Ipv6Address*)this)->CombinePrefix (Ipv6Prefix (64)) == linkLocal) |
536 { |
536 { |
537 return true; |
537 return true; |
538 } |
538 } |
539 return false; |
539 return false; |
540 } |
540 } |
541 |
541 |
542 bool Ipv6Address::IsEqual (const Ipv6Address& other) const |
542 bool Ipv6Address::IsEqual (const Ipv6Address& other) const |
543 { |
543 { |
544 if (!memcmp (m_address, other.m_address, 16)) |
544 if (!memcmp (m_address, other.m_address, 16)) |
545 { |
545 { |
546 return true; |
546 return true; |
547 } |
547 } |
548 return false; |
548 return false; |
549 } |
549 } |
550 |
550 |
551 std::ostream& operator << (std::ostream& os, Ipv6Address const& address) |
551 std::ostream& operator << (std::ostream& os, Ipv6Address const& address) |
552 { |
552 { |
591 mod = prefix % 8; |
591 mod = prefix % 8; |
592 |
592 |
593 memset (m_prefix, 0xff, nb); |
593 memset (m_prefix, 0xff, nb); |
594 |
594 |
595 if (mod) |
595 if (mod) |
596 { |
596 { |
597 m_prefix[nb] = 0xff << (8-mod); |
597 m_prefix[nb] = 0xff << (8-mod); |
598 } |
598 } |
599 |
599 |
600 if (nb < 16) |
600 if (nb < 16) |
601 { |
601 { |
602 nb++; |
602 nb++; |
603 for (i = nb; i < 16 ; i++) |
603 for (i = nb; i < 16 ; i++) |
604 { |
604 { |
605 m_prefix[i] = 0x00; |
605 m_prefix[i] = 0x00; |
606 } |
606 } |
607 } |
607 } |
608 } |
608 } |
609 |
609 |
610 Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix) |
610 Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix) |
611 { |
611 { |
612 memcpy (m_prefix, prefix.m_prefix, 16); |
612 memcpy (m_prefix, prefix.m_prefix, 16); |
689 { |
689 { |
690 uint8_t i = 0; |
690 uint8_t i = 0; |
691 uint8_t prefixLength = 0; |
691 uint8_t prefixLength = 0; |
692 |
692 |
693 for(i = 0 ; i < 16 ; i++) |
693 for(i = 0 ; i < 16 ; i++) |
694 { |
694 { |
695 uint8_t mask = m_prefix[i]; |
695 uint8_t mask = m_prefix[i]; |
696 |
696 |
697 while(mask != 0) |
697 while(mask != 0) |
698 { |
698 { |
699 mask = mask << 1; |
699 mask = mask << 1; |
700 prefixLength++; |
700 prefixLength++; |
701 } |
701 } |
702 } |
702 } |
703 |
703 |
704 return prefixLength; |
704 return prefixLength; |
705 } |
705 } |
706 |
706 |
707 bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const |
707 bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const |
708 { |
708 { |
709 if (!memcmp (m_prefix, other.m_prefix, 16)) |
709 if (!memcmp (m_prefix, other.m_prefix, 16)) |
710 { |
710 { |
711 return true; |
711 return true; |
712 } |
712 } |
713 return false; |
713 return false; |
714 } |
714 } |
715 |
715 |
716 std::ostream& operator << (std::ostream& os, Ipv6Prefix const& prefix) |
716 std::ostream& operator << (std::ostream& os, Ipv6Prefix const& prefix) |
717 { |
717 { |