mac.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2022 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 "mac.h"
  20. #include "config.h"
  21. #include "common.h"
  22. #include <ctype.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. /**
  26. * converts a string representation of a MAC address, based on
  27. * non-portable ether_aton()
  28. */
  29. void
  30. mac2hex(const char *mac, u_char *dst, int len)
  31. {
  32. int i;
  33. char *pp;
  34. if (len < 6)
  35. return;
  36. while (isspace(*mac))
  37. mac++;
  38. /* expect 6 hex octets separated by ':' or space/NUL if last octet */
  39. for (i = 0; i < 6; i++) {
  40. long l = strtol(mac, &pp, 16);
  41. if (pp == mac || l > 0xFF || l < 0)
  42. return;
  43. if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
  44. return;
  45. dst[i] = (u_char)l;
  46. mac = pp + 1;
  47. }
  48. }
  49. /**
  50. * converts a string representation of TWO MAC addresses, which
  51. * are comma deliminated into two hex values. Either *first or *second
  52. * can be NULL if there is nothing before or after the comma.
  53. * returns:
  54. * 1 = first mac
  55. * 2 = second mac
  56. * 3 = both mac's
  57. * 0 = none
  58. */
  59. int
  60. dualmac2hex(const char *dualmac, u_char *first, u_char *second, int len)
  61. {
  62. char *tok = NULL, *temp, *string;
  63. int ret = 0;
  64. string = safe_strdup(dualmac);
  65. /* if we've only got a comma, then return NULL's */
  66. if (len <= 1)
  67. goto done;
  68. temp = strtok_r(string, ",", &tok);
  69. if (strlen(temp)) {
  70. mac2hex(temp, first, len);
  71. ret = 1;
  72. }
  73. temp = strtok_r(NULL, ",", &tok);
  74. /* temp is null if no comma */
  75. if (temp != NULL) {
  76. if (strlen(temp)) {
  77. mac2hex(temp, second, len);
  78. ret += 2;
  79. }
  80. }
  81. done:
  82. safe_free(string);
  83. return ret;
  84. }
  85. /**
  86. * Figures out if a MAC is listed in a comma delimited
  87. * string of MAC addresses.
  88. * returns TCPR_DIR_C2S if listed
  89. * returns TCPR_DIR_S2C if not listed
  90. */
  91. tcpr_dir_t
  92. macinstring(const char *macstring, const u_char *mac)
  93. {
  94. char *tok = NULL, *tempstr, *ourstring;
  95. u_char tempmac[6];
  96. int len = 6, ret = TCPR_DIR_S2C;
  97. ourstring = safe_strdup(macstring);
  98. memset(&tempmac[0], 0, sizeof(tempmac));
  99. tempstr = strtok_r(ourstring, ",", &tok);
  100. if (tempstr != NULL && strlen(tempstr)) {
  101. mac2hex(tempstr, tempmac, len);
  102. if (memcmp(mac, tempmac, len) == 0) {
  103. dbgx(3, "Packet matches: " MAC_FORMAT " sending out primary.\n", MAC_STR(tempmac));
  104. ret = TCPR_DIR_C2S;
  105. goto EXIT_MACINSTRING;
  106. }
  107. } else {
  108. goto EXIT_MACINSTRING;
  109. }
  110. while ((tempstr = strtok_r(NULL, ",", &tok)) != NULL) {
  111. mac2hex(tempstr, tempmac, len);
  112. if (memcmp(mac, tempmac, len) == 0) {
  113. ret = TCPR_DIR_C2S;
  114. dbgx(3, "Packet matches: " MAC_FORMAT " sending out primary.\n", MAC_STR(tempmac));
  115. goto EXIT_MACINSTRING;
  116. }
  117. }
  118. EXIT_MACINSTRING:
  119. safe_free(ourstring);
  120. #ifdef DEBUG
  121. if (ret == TCPR_DIR_S2C)
  122. dbg(3, "Packet doesn't match any MAC addresses sending out secondary.\n");
  123. #endif
  124. return ret;
  125. }