AddrTools.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #ifndef AddrTools_H
  16. #define AddrTools_H
  17. #include "util/Bits.h"
  18. #include "util/Endian.h"
  19. #include "util/Hex.h"
  20. #include "util/platform/Sockaddr.h"
  21. #include <stdint.h>
  22. /** Takes the path in host byte order. */
  23. static inline void AddrTools_printPath(uint8_t out[20], uint64_t path)
  24. {
  25. uint64_t path_be = Endian_hostToBigEndian64(path);
  26. uint8_t bytes[16];
  27. Hex_encode(bytes, 16, (uint8_t*) &path_be, 8);
  28. out[ 0] = bytes[ 0];
  29. out[ 1] = bytes[ 1];
  30. out[ 2] = bytes[ 2];
  31. out[ 3] = bytes[ 3];
  32. out[ 4] = '.';
  33. out[ 5] = bytes[ 4];
  34. out[ 6] = bytes[ 5];
  35. out[ 7] = bytes[ 6];
  36. out[ 8] = bytes[ 7];
  37. out[ 9] = '.';
  38. out[10] = bytes[ 8];
  39. out[11] = bytes[ 9];
  40. out[12] = bytes[10];
  41. out[13] = bytes[11];
  42. out[14] = '.';
  43. out[15] = bytes[12];
  44. out[16] = bytes[13];
  45. out[17] = bytes[14];
  46. out[18] = bytes[15];
  47. out[19] = '\0';
  48. }
  49. /**
  50. * Parse out a path.
  51. *
  52. * @param out a pointer to a number which will be set to the path in HOST BYTE ORDER.
  53. * @param netAddr a string representation of the path such as "0000.1111.2222.3333" in Big Endian.
  54. * @return 0 if successful, -1 if the netAddr is malformed.
  55. */
  56. static inline int AddrTools_parsePath(uint64_t* out, const uint8_t netAddr[20])
  57. {
  58. if (netAddr[4] != '.' || netAddr[9] != '.' || netAddr[14] != '.' || netAddr[19] != '\0') {
  59. return -1;
  60. }
  61. uint8_t hex[16] = {
  62. netAddr[ 0],
  63. netAddr[ 1],
  64. netAddr[ 2],
  65. netAddr[ 3],
  66. netAddr[ 5],
  67. netAddr[ 6],
  68. netAddr[ 7],
  69. netAddr[ 8],
  70. netAddr[10],
  71. netAddr[11],
  72. netAddr[12],
  73. netAddr[13],
  74. netAddr[15],
  75. netAddr[16],
  76. netAddr[17],
  77. netAddr[18]
  78. };
  79. uint8_t numberBytes[8];
  80. if (Hex_decode(numberBytes, 8, hex, 16) != 8) {
  81. return -1;
  82. }
  83. uint64_t out_be;
  84. Bits_memcpyConst(&out_be, numberBytes, 8);
  85. *out = Endian_bigEndianToHost64(out_be);
  86. return 0;
  87. }
  88. static inline void AddrTools_printIp(uint8_t output[40], const uint8_t binIp[16])
  89. {
  90. uint8_t hex[32];
  91. Hex_encode(hex, 32, binIp, 16);
  92. output[ 0] = hex[ 0];
  93. output[ 1] = hex[ 1];
  94. output[ 2] = hex[ 2];
  95. output[ 3] = hex[ 3];
  96. output[ 4] = ':';
  97. output[ 5] = hex[ 4];
  98. output[ 6] = hex[ 5];
  99. output[ 7] = hex[ 6];
  100. output[ 8] = hex[ 7];
  101. output[ 9] = ':';
  102. output[10] = hex[ 8];
  103. output[11] = hex[ 9];
  104. output[12] = hex[10];
  105. output[13] = hex[11];
  106. output[14] = ':';
  107. output[15] = hex[12];
  108. output[16] = hex[13];
  109. output[17] = hex[14];
  110. output[18] = hex[15];
  111. output[19] = ':';
  112. output[20] = hex[16];
  113. output[21] = hex[17];
  114. output[22] = hex[18];
  115. output[23] = hex[19];
  116. output[24] = ':';
  117. output[25] = hex[20];
  118. output[26] = hex[21];
  119. output[27] = hex[22];
  120. output[28] = hex[23];
  121. output[29] = ':';
  122. output[30] = hex[24];
  123. output[31] = hex[25];
  124. output[32] = hex[26];
  125. output[33] = hex[27];
  126. output[34] = ':';
  127. output[35] = hex[28];
  128. output[36] = hex[29];
  129. output[37] = hex[30];
  130. output[38] = hex[31];
  131. output[39] = '\0';
  132. }
  133. static inline void AddrTools_printShortIp(uint8_t output[40], const uint8_t binIp[16])
  134. {
  135. /* The chances of hitting :0:0: and breaking
  136. * RFC5952 are 1 in (1 / (2^16))^2 * 6.
  137. * E. Siler
  138. */
  139. char *p = output;
  140. int i = 0;
  141. for (; i < 16;) {
  142. if ((size_t)p != (size_t)output) {
  143. *p++= ':';
  144. }
  145. if (binIp[i] > 0x0F) {
  146. Hex_encode(p, 2, &binIp[i++], 1);
  147. p += 2;
  148. } else if (binIp[i] > 0x00) {
  149. *p++ = Hex_encodeLowNibble(binIp[i++]);
  150. } else {
  151. ++i;
  152. if (binIp[i] > 0x0F) {
  153. Hex_encode(p, 2, &binIp[i++], 1);
  154. p += 2;
  155. } else {
  156. *p++ = Hex_encodeLowNibble(binIp[i++]);
  157. }
  158. continue;
  159. }
  160. Hex_encode(p, 2, &binIp[i++], 1);
  161. p += 2;
  162. }
  163. *p = '\0';
  164. Assert_true((size_t)p <= ((size_t)output + 40));
  165. Assert_true(i <= 16);
  166. }
  167. /**
  168. * Parse out an address.
  169. *
  170. * @param out a pointer to a byte array which will be set to the bytes of the ipv6 address.
  171. * @param hexAddr a string representation of the ipv6 address such as:
  172. * "fc4f:630d:e499:8f5b:c49f:6e6b:01ae:3120".
  173. * @return 0 if successful, -1 if the hexAddr is malformed.
  174. */
  175. static inline int AddrTools_parseIp(uint8_t out[16], const uint8_t hexAddr[40])
  176. {
  177. struct Sockaddr_storage ss;
  178. if (Sockaddr_parse((const char*) hexAddr, &ss)
  179. || Sockaddr_getFamily(&ss.addr) != Sockaddr_AF_INET6)
  180. {
  181. return -1;
  182. }
  183. uint8_t* addr = NULL;
  184. Sockaddr_getAddress(&ss.addr, &addr);
  185. Bits_memcpyConst(out, addr, 16);
  186. return 0;
  187. }
  188. /**
  189. * Parse out an ethernet MAC address.
  190. *
  191. * @param out a pointer to a byte array which will be set to the bytes of the MAC address.
  192. * @param hexAddr a string representation of an ethernet MAC address such as:
  193. * "00:11:22:33:44:55"
  194. * @return 0 if successful, -1 if the hexAddr is malformed.
  195. */
  196. static inline int AddrTools_parseMac(uint8_t out[6], const uint8_t hexAddr[17])
  197. {
  198. for (int i = 2; i < 15; i += 3) {
  199. if (hexAddr[i] != ':') {
  200. return -1;
  201. }
  202. }
  203. uint8_t hex[12];
  204. int j = 0;
  205. for (int i = 0; i < 18; i++) {
  206. hex[j++] = hexAddr[i++];
  207. hex[j++] = hexAddr[i++];
  208. }
  209. if (Hex_decode(out, 6, hex, 12) != 6) {
  210. return -1;
  211. }
  212. return 0;
  213. }
  214. static inline void AddrTools_printMac(uint8_t output[18], const uint8_t binMac[6])
  215. {
  216. uint8_t hex[12];
  217. Hex_encode(hex, 12, binMac, 6);
  218. output[ 0] = hex[ 0];
  219. output[ 1] = hex[ 1];
  220. output[ 2] = ':';
  221. output[ 3] = hex[ 2];
  222. output[ 4] = hex[ 3];
  223. output[ 5] = ':';
  224. output[ 6] = hex[ 4];
  225. output[ 7] = hex[ 5];
  226. output[ 8] = ':';
  227. output[ 9] = hex[ 6];
  228. output[10] = hex[ 7];
  229. output[11] = ':';
  230. output[12] = hex[ 8];
  231. output[13] = hex[ 9];
  232. output[14] = ':';
  233. output[15] = hex[10];
  234. output[16] = hex[11];
  235. output[17] = '\0';
  236. }
  237. #endif