trunnel.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /* trunnel.c -- Helper functions to implement trunnel.
  2. *
  3. * Copyright 2014, The Tor Project, Inc.
  4. * See license at the end of this file for copying information.
  5. *
  6. * See trunnel-impl.h for documentation of these functions.
  7. */
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "trunnel-impl.h"
  11. #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
  12. __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  13. # define IS_LITTLE_ENDIAN 1
  14. #elif defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \
  15. BYTE_ORDER == __ORDER_LITTLE_ENDIAN
  16. # define IS_LITTLE_ENDIAN 1
  17. #elif defined(_WIN32)
  18. # define IS_LITTLE_ENDIAN 1
  19. #elif defined(__APPLE__)
  20. # include <libkern/OSByteOrder.h>
  21. # define BSWAP64(x) OSSwapLittleToHostInt64(x)
  22. #elif defined(sun) || defined(__sun)
  23. # include <sys/byteorder.h>
  24. # ifndef _BIG_ENDIAN
  25. # define IS_LITTLE_ENDIAN
  26. # endif
  27. #else
  28. # if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
  29. # include <sys/endian.h>
  30. # else
  31. # include <endian.h>
  32. # endif
  33. # if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
  34. __BYTE_ORDER == __LITTLE_ENDIAN
  35. # define IS_LITTLE_ENDIAN
  36. # endif
  37. #endif
  38. #ifdef _WIN32
  39. uint16_t
  40. trunnel_htons(uint16_t s)
  41. {
  42. return (s << 8) | (s >> 8);
  43. }
  44. uint16_t
  45. trunnel_ntohs(uint16_t s)
  46. {
  47. return (s << 8) | (s >> 8);
  48. }
  49. uint32_t
  50. trunnel_htonl(uint32_t s)
  51. {
  52. return (s << 24) |
  53. ((s << 8)&0xff0000) |
  54. ((s >> 8)&0xff00) |
  55. (s >> 24);
  56. }
  57. uint32_t
  58. trunnel_ntohl(uint32_t s)
  59. {
  60. return (s << 24) |
  61. ((s << 8)&0xff0000) |
  62. ((s >> 8)&0xff00) |
  63. (s >> 24);
  64. }
  65. #endif
  66. uint64_t
  67. trunnel_htonll(uint64_t a)
  68. {
  69. #ifdef IS_LITTLE_ENDIAN
  70. return trunnel_htonl(a>>32) | (((uint64_t)trunnel_htonl(a))<<32);
  71. #else
  72. return a;
  73. #endif
  74. }
  75. uint64_t
  76. trunnel_ntohll(uint64_t a)
  77. {
  78. return trunnel_htonll(a);
  79. }
  80. #ifdef TRUNNEL_DEBUG_FAILING_ALLOC
  81. /** Used for debugging and running tricky test cases: Makes the nth
  82. * memoryation allocation call from now fail.
  83. */
  84. int trunnel_provoke_alloc_failure = 0;
  85. #endif
  86. void *
  87. trunnel_dynarray_expand(size_t *allocated_p, void *ptr,
  88. size_t howmanymore, size_t eltsize)
  89. {
  90. size_t newsize = howmanymore + *allocated_p;
  91. void *newarray = NULL;
  92. if (newsize < 8)
  93. newsize = 8;
  94. if (newsize < *allocated_p * 2)
  95. newsize = *allocated_p * 2;
  96. if (newsize <= *allocated_p || newsize < howmanymore)
  97. return NULL;
  98. newarray = trunnel_reallocarray(ptr, newsize, eltsize);
  99. if (newarray == NULL)
  100. return NULL;
  101. *allocated_p = newsize;
  102. return newarray;
  103. }
  104. #ifndef trunnel_reallocarray
  105. void *
  106. trunnel_reallocarray(void *a, size_t x, size_t y)
  107. {
  108. #ifdef TRUNNEL_DEBUG_FAILING_ALLOC
  109. if (trunnel_provoke_alloc_failure) {
  110. if (--trunnel_provoke_alloc_failure == 0)
  111. return NULL;
  112. }
  113. #endif
  114. if (x > SIZE_MAX / y)
  115. return NULL;
  116. return trunnel_realloc(a, x * y);
  117. }
  118. #endif
  119. const char *
  120. trunnel_string_getstr(trunnel_string_t *str)
  121. {
  122. trunnel_assert(str->allocated_ >= str->n_);
  123. if (str->allocated_ == str->n_) {
  124. TRUNNEL_DYNARRAY_EXPAND(char, str, 1, {});
  125. }
  126. str->elts_[str->n_] = 0;
  127. return str->elts_;
  128. trunnel_alloc_failed:
  129. return NULL;
  130. }
  131. int
  132. trunnel_string_setstr0(trunnel_string_t *str, const char *val, size_t len,
  133. uint8_t *errcode_ptr)
  134. {
  135. if (len == SIZE_MAX)
  136. goto trunnel_alloc_failed;
  137. if (str->allocated_ <= len) {
  138. TRUNNEL_DYNARRAY_EXPAND(char, str, len + 1 - str->allocated_, {});
  139. }
  140. memcpy(str->elts_, val, len);
  141. str->n_ = len;
  142. str->elts_[len] = 0;
  143. return 0;
  144. trunnel_alloc_failed:
  145. *errcode_ptr = 1;
  146. return -1;
  147. }
  148. int
  149. trunnel_string_setlen(trunnel_string_t *str, size_t newlen,
  150. uint8_t *errcode_ptr)
  151. {
  152. if (newlen == SIZE_MAX)
  153. goto trunnel_alloc_failed;
  154. if (str->allocated_ < newlen + 1) {
  155. TRUNNEL_DYNARRAY_EXPAND(char, str, newlen + 1 - str->allocated_, {});
  156. }
  157. if (str->n_ < newlen) {
  158. memset(& (str->elts_[str->n_]), 0, (newlen - str->n_));
  159. }
  160. str->n_ = newlen;
  161. str->elts_[newlen] = 0;
  162. return 0;
  163. trunnel_alloc_failed:
  164. *errcode_ptr = 1;
  165. return -1;
  166. }
  167. void *
  168. trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p,
  169. void *ptr, size_t newlen,
  170. size_t eltsize, trunnel_free_fn_t free_fn,
  171. uint8_t *errcode_ptr)
  172. {
  173. if (*allocated_p < newlen) {
  174. void *newptr = trunnel_dynarray_expand(allocated_p, ptr,
  175. newlen - *allocated_p, eltsize);
  176. if (newptr == NULL)
  177. goto trunnel_alloc_failed;
  178. ptr = newptr;
  179. }
  180. if (free_fn && *len_p > newlen) {
  181. size_t i;
  182. void **elts = (void **) ptr;
  183. for (i = newlen; i < *len_p; ++i) {
  184. free_fn(elts[i]);
  185. elts[i] = NULL;
  186. }
  187. }
  188. if (*len_p < newlen) {
  189. memset( ((char*)ptr) + (eltsize * *len_p), 0, (newlen - *len_p) * eltsize);
  190. }
  191. *len_p = newlen;
  192. return ptr;
  193. trunnel_alloc_failed:
  194. *errcode_ptr = 1;
  195. return NULL;
  196. }
  197. /*
  198. Copyright 2014 The Tor Project, Inc.
  199. Redistribution and use in source and binary forms, with or without
  200. modification, are permitted provided that the following conditions are
  201. met:
  202. * Redistributions of source code must retain the above copyright
  203. notice, this list of conditions and the following disclaimer.
  204. * Redistributions in binary form must reproduce the above
  205. copyright notice, this list of conditions and the following disclaimer
  206. in the documentation and/or other materials provided with the
  207. distribution.
  208. * Neither the names of the copyright owners nor the names of its
  209. contributors may be used to endorse or promote products derived from
  210. this software without specific prior written permission.
  211. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  212. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  213. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  214. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  215. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  216. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  217. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  218. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  219. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  220. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  221. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  222. */