utils.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2017 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
  5. *
  6. * The Tcpreplay Suite of tools is free software: you can redistribute it
  7. * and/or modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or with the authors permission any later version.
  10. *
  11. * The Tcpreplay Suite is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "config.h"
  20. #include "defines.h"
  21. #include "common.h"
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <errno.h>
  25. #include <ctype.h>
  26. #include <unistd.h>
  27. #ifdef DEBUG
  28. extern int debug;
  29. #endif
  30. /**
  31. * this is wrapped up in a #define safe_malloc
  32. * This function, detects failures to malloc memory and zeros out the
  33. * memory before returning
  34. */
  35. void *
  36. _our_safe_malloc(size_t len, const char *funcname, const int line, const char *file)
  37. {
  38. u_char *ptr;
  39. if ((ptr = malloc(len)) == NULL) {
  40. fprintf(stderr, "ERROR in %s:%s() line %d: Unable to malloc() %zu bytes", file, funcname, line, len);
  41. exit(-1);
  42. }
  43. /* zero memory */
  44. memset(ptr, 0, len);
  45. /* wrapped inside an #ifdef for better performance */
  46. dbgx(5, "Malloc'd %zu bytes in %s:%s() line %d", len, file, funcname, line);
  47. return (void *)ptr;
  48. }
  49. /**
  50. * this is wrapped up in a #define safe_realloc
  51. * This function, detects failures to realloc memory and zeros
  52. * out the NEW memory if len > current len. As always, remember
  53. * to use it as:
  54. * ptr = safe_realloc(ptr, size)
  55. */
  56. void *
  57. _our_safe_realloc(void *ptr, size_t len, const char *funcname, const int line, const char *file)
  58. {
  59. if ((ptr = realloc(ptr, len)) == NULL) {
  60. fprintf(stderr, "ERROR: in %s:%s() line %d: Unable to remalloc() buffer to %zu bytes", file, funcname, line, len);
  61. exit(-1);
  62. }
  63. dbgx(5, "Remalloc'd buffer to %zu bytes in %s:%s() line %d", len, file, funcname, line);
  64. return ptr;
  65. }
  66. /**
  67. * this is wrapped up in a #define safe_strdup
  68. * This function, detects failures to realloc memory
  69. */
  70. char *
  71. _our_safe_strdup(const char *str, const char *funcname, const int line, const char *file)
  72. {
  73. char *newstr;
  74. if ((newstr = (char *)malloc(strlen(str) + 1)) == NULL) {
  75. fprintf(stderr, "ERROR in %s:%s() line %d: Unable to strdup() %zu bytes\n", file, funcname, line, strlen(str));
  76. exit(-1);
  77. }
  78. memcpy(newstr, str, strlen(str) + 1);
  79. return newstr;
  80. }
  81. /**
  82. * calls free and sets to NULL.
  83. */
  84. void
  85. _our_safe_free(void *ptr, const char *funcname, const int line, const char *file)
  86. {
  87. assert(funcname);
  88. assert(line);
  89. assert(file);
  90. if (ptr == NULL)
  91. return;
  92. free(ptr);
  93. ptr = NULL;
  94. }
  95. /**
  96. * Print various packet statistics
  97. */
  98. void
  99. packet_stats(const tcpreplay_stats_t *stats)
  100. {
  101. struct timeval diff;
  102. COUNTER diff_us;
  103. COUNTER bytes_sec = 0;
  104. u_int32_t bytes_sec_10ths = 0;
  105. COUNTER mb_sec = 0;
  106. u_int32_t mb_sec_100ths = 0;
  107. u_int32_t mb_sec_1000ths = 0;
  108. COUNTER pkts_sec = 0;
  109. u_int32_t pkts_sec_100ths = 0;
  110. timersub(&stats->end_time, &stats->start_time, &diff);
  111. diff_us = TIMEVAL_TO_MICROSEC(&diff);
  112. if (diff_us && stats->pkts_sent && stats->bytes_sent) {
  113. COUNTER bytes_sec_X10;
  114. COUNTER pkts_sec_X100;
  115. COUNTER mb_sec_X1000;
  116. COUNTER mb_sec_X100;
  117. if (stats->bytes_sent > 1000 * 1000 * 1000 && diff_us > 1000 * 1000) {
  118. bytes_sec_X10 = (stats->bytes_sent * 10 * 1000) / (diff_us / 1000);
  119. pkts_sec_X100 = (stats->pkts_sent * 100 * 1000) / (diff_us / 1000);
  120. } else {
  121. bytes_sec_X10 = (stats->bytes_sent * 10 * 1000 * 1000) / diff_us;
  122. pkts_sec_X100 = (stats->pkts_sent * 100 * 1000 * 1000) / diff_us;
  123. }
  124. bytes_sec = bytes_sec_X10 / 10;
  125. bytes_sec_10ths = bytes_sec_X10 % 10;
  126. mb_sec_X1000 = (bytes_sec * 8) / 1000;
  127. mb_sec_X100 = mb_sec_X1000 / 10;
  128. mb_sec = mb_sec_X1000 / 1000;
  129. mb_sec_100ths = mb_sec_X100 % 100;
  130. mb_sec_1000ths = mb_sec_X1000 % 1000;
  131. pkts_sec = pkts_sec_X100 / 100;
  132. pkts_sec_100ths = pkts_sec_X100 % 100;
  133. }
  134. if (diff_us >= 1000 * 1000)
  135. printf("Actual: " COUNTER_SPEC " packets (" COUNTER_SPEC " bytes) sent in %zd.%02zd seconds\n",
  136. stats->pkts_sent, stats->bytes_sent, (ssize_t)diff.tv_sec, (ssize_t)(diff.tv_usec / (10 * 1000)));
  137. else
  138. printf("Actual: " COUNTER_SPEC " packets (" COUNTER_SPEC " bytes) sent in %zd.%06zd seconds\n",
  139. stats->pkts_sent, stats->bytes_sent, (ssize_t)diff.tv_sec, (ssize_t)diff.tv_usec);
  140. if (mb_sec >= 1)
  141. printf("Rated: %llu.%1u Bps, %llu.%02u Mbps, %llu.%02u pps\n",
  142. bytes_sec, bytes_sec_10ths, mb_sec, mb_sec_100ths, pkts_sec, pkts_sec_100ths);
  143. else
  144. printf("Rated: %llu.%1u Bps, %llu.%03u Mbps, %llu.%02u pps\n",
  145. bytes_sec, bytes_sec_10ths, mb_sec, mb_sec_1000ths, pkts_sec, pkts_sec_100ths);
  146. fflush(NULL);
  147. if (stats->failed)
  148. printf("Failed write attempts: " COUNTER_SPEC "\n",
  149. stats->failed);
  150. }
  151. /**
  152. * fills a buffer with a string representing the given time
  153. *
  154. * @param when: the time that should be formatted
  155. * @param buf: a buffer to write to
  156. * @param len: length of the buffer
  157. * @return: string containing date, or -1 on error
  158. */
  159. int format_date_time(struct timeval *when, char *buf, size_t len)
  160. {
  161. struct tm *tm;
  162. char tmp[64];
  163. assert(len);
  164. tm = localtime(&when->tv_sec);
  165. if (!tm)
  166. return -1;
  167. strftime(tmp, sizeof tmp, "%Y-%m-%d %H:%M:%S.%%06u", tm);
  168. return snprintf(buf, len, tmp, when->tv_usec);
  169. }
  170. /**
  171. * reads a hexstring in the format of xx,xx,xx,xx spits it back into *hex
  172. * up to hexlen bytes. Returns actual number of bytes returned. On error
  173. * it just calls errx() since all errors are fatal.
  174. */
  175. int
  176. read_hexstring(const char *l2string, u_char *hex, const int hexlen)
  177. {
  178. int numbytes = 0;
  179. unsigned int value;
  180. char *l2byte;
  181. u_char databyte;
  182. char *token = NULL;
  183. char *string;
  184. string = safe_strdup(l2string);
  185. if (hexlen <= 0)
  186. err(-1, "Hex buffer must be > 0");
  187. memset(hex, '\0', hexlen);
  188. /* data is hex, comma seperated, byte by byte */
  189. /* get the first byte */
  190. l2byte = strtok_r(string, ",", &token);
  191. sscanf(l2byte, "%x", &value);
  192. if (value > 0xff)
  193. errx(-1, "Invalid hex string byte: %s", l2byte);
  194. databyte = (u_char) value;
  195. memcpy(&hex[numbytes], &databyte, 1);
  196. /* get remaining bytes */
  197. while ((l2byte = strtok_r(NULL, ",", &token)) != NULL) {
  198. numbytes++;
  199. if (numbytes + 1 > hexlen) {
  200. warn("Hex buffer too small for data- skipping data");
  201. goto done;
  202. }
  203. sscanf(l2byte, "%x", &value);
  204. if (value > 0xff)
  205. errx(-1, "Invalid hex string byte: %s", l2byte);
  206. databyte = (u_char) value;
  207. memcpy(&hex[numbytes], &databyte, 1);
  208. }
  209. numbytes++;
  210. done:
  211. safe_free(string);
  212. dbgx(1, "Read %d bytes of hex data", numbytes);
  213. return (numbytes);
  214. }
  215. #ifdef USE_CUSTOM_INET_ATON
  216. int
  217. inet_aton(const char *name, struct in_addr *addr)
  218. {
  219. in_addr_t a = inet_addr(name);
  220. addr->s_addr = a;
  221. return a != (in_addr_t)-1;
  222. }
  223. #endif
  224. #if SIZEOF_CHARP == 4
  225. uint32_t __div64_32(uint64_t *n, uint32_t base)
  226. {
  227. uint64_t rem = *n;
  228. uint64_t b = base;
  229. uint64_t res, d = 1;
  230. uint32_t high = rem >> 32;
  231. /* Reduce the thing a bit first */
  232. res = 0;
  233. if (high >= base) {
  234. high /= base;
  235. res = (uint64_t) high << 32;
  236. rem -= (uint64_t) (high*base) << 32;
  237. }
  238. while ((int64_t)b > 0 && b < rem) {
  239. b = b+b;
  240. d = d+d;
  241. }
  242. do {
  243. if (rem >= b) {
  244. rem -= b;
  245. res += d;
  246. }
  247. b >>= 1;
  248. d >>= 1;
  249. } while (d);
  250. *n = res;
  251. return rem;
  252. }
  253. #endif /* SIZEOF_CHARP == 4 */
  254. /**
  255. * Implementation of rand_r that is consistent across all platforms
  256. * This algorithm is mentioned in the ISO C standard, here extended
  257. * for 32 bits.
  258. * @param: seed
  259. * @return: random number
  260. */
  261. int tcpr_random(uint32_t *seed)
  262. {
  263. unsigned int next = *seed;
  264. int result;
  265. next *= 1103515245;
  266. next += 12345;
  267. result = (unsigned int) (next / 65536) % 2048;
  268. next *= 1103515245;
  269. next += 12345;
  270. result <<= 10;
  271. result ^= (unsigned int) (next / 65536) % 1024;
  272. next *= 1103515245;
  273. next += 12345;
  274. result <<= 10;
  275. result ^= (unsigned int) (next / 65536) % 1024;
  276. *seed = next;
  277. return result;
  278. }