forked from appneta/tcpreplay
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mac.c
147 lines (129 loc) · 3.85 KB
/
mac.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* $Id$ */
/*
* Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
* Copyright (c) 2013-2018 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
*
* The Tcpreplay Suite of tools is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or with the authors permission any later version.
*
* The Tcpreplay Suite is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "defines.h"
#include "common.h"
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include "mac.h"
/**
* converts a string representation of a MAC address, based on
* non-portable ether_aton()
*/
void
mac2hex(const char *mac, u_char *dst, int len)
{
int i;
char *pp;
if (len < 6)
return;
while (isspace(*mac))
mac++;
/* expect 6 hex octets separated by ':' or space/NUL if last octet */
for (i = 0; i < 6; i++) {
long l = strtol(mac, &pp, 16);
if (pp == mac || l > 0xFF || l < 0)
return;
if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
return;
dst[i] = (u_char) l;
mac = pp + 1;
}
}
/**
* converts a string representation of TWO MAC addresses, which
* are comma deliminated into two hex values. Either *first or *second
* can be NULL if there is nothing before or after the comma.
* returns:
* 1 = first mac
* 2 = second mac
* 3 = both mac's
* 0 = none
*/
int
dualmac2hex(const char *dualmac, u_char *first, u_char *second, int len)
{
char *tok = NULL, *temp, *string;
int ret = 0;
string = safe_strdup(dualmac);
/* if we've only got a comma, then return NULL's */
if (len <= 1) {
second = first = NULL;
goto done;
}
temp = strtok_r(string, ",", &tok);
if (strlen(temp)) {
mac2hex(temp, first, len);
ret = 1;
}
temp = strtok_r(NULL, ",", &tok);
/* temp is null if no comma */
if (temp != NULL) {
if (strlen(temp)) {
mac2hex(temp, second, len);
ret += 2;
}
}
done:
safe_free(string);
return ret;
}
/**
* Figures out if a MAC is listed in a comma delimited
* string of MAC addresses.
* returns TCPR_DIR_C2S if listed
* returns TCPR_DIR_S2C if not listed
*/
tcpr_dir_t
macinstring(const char *macstring, const u_char *mac)
{
char *tok = NULL, *tempstr, *ourstring;
u_char tempmac[6];
int len = 6, ret = TCPR_DIR_S2C;
ourstring = safe_strdup(macstring);
memset(&tempmac[0], 0, sizeof(tempmac));
tempstr = strtok_r(ourstring, ",", &tok);
if (strlen(tempstr)) {
mac2hex(tempstr, tempmac, len);
if (memcmp(mac, tempmac, len) == 0) {
dbgx(3, "Packet matches: " MAC_FORMAT " sending out primary.\n", MAC_STR(tempmac));
ret = TCPR_DIR_C2S;
goto EXIT_MACINSTRING;
}
} else {
goto EXIT_MACINSTRING;
}
while ((tempstr = strtok_r(NULL, ",", &tok)) != NULL) {
mac2hex(tempstr, tempmac, len);
if (memcmp(mac, tempmac, len) == 0) {
ret = TCPR_DIR_C2S;
dbgx(3, "Packet matches: " MAC_FORMAT " sending out primary.\n", MAC_STR(tempmac));
goto EXIT_MACINSTRING;
}
}
EXIT_MACINSTRING:
safe_free(ourstring);
#ifdef DEBUG
if (ret == TCPR_DIR_S2C)
dbg(3, "Packet doesn't match any MAC addresses sending out secondary.\n");
#endif
return ret;
}