|
mathieu@1181
|
1 |
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
|
mathieu@1181
|
2 |
/*
|
|
mathieu@1181
|
3 |
* Copyright (c) 2007 INRIA
|
|
mathieu@1181
|
4 |
*
|
|
mathieu@1181
|
5 |
* This program is free software; you can redistribute it and/or modify
|
|
mathieu@1181
|
6 |
* it under the terms of the GNU General Public License version 2 as
|
|
mathieu@1181
|
7 |
* published by the Free Software Foundation;
|
|
mathieu@1181
|
8 |
*
|
|
mathieu@1181
|
9 |
* This program is distributed in the hope that it will be useful,
|
|
mathieu@1181
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
mathieu@1181
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
mathieu@1181
|
12 |
* GNU General Public License for more details.
|
|
mathieu@1181
|
13 |
*
|
|
mathieu@1181
|
14 |
* You should have received a copy of the GNU General Public License
|
|
mathieu@1181
|
15 |
* along with this program; if not, write to the Free Software
|
|
mathieu@1181
|
16 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
mathieu@1181
|
17 |
*
|
|
mathieu@1181
|
18 |
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
|
mathieu@1181
|
19 |
*/
|
|
mathieu@1494
|
20 |
#include "mac48-address.h"
|
|
mathieu@1158
|
21 |
#include "address.h"
|
|
mathieu@1158
|
22 |
#include "ns3/assert.h"
|
|
mathieu@1167
|
23 |
#include <iomanip>
|
|
mathieu@1170
|
24 |
#include <iostream>
|
|
mathieu@3365
|
25 |
#include <string.h>
|
|
mathieu@1158
|
26 |
|
|
mathieu@1158
|
27 |
namespace ns3 {
|
|
mathieu@1158
|
28 |
|
|
mathieu@2582
|
29 |
ATTRIBUTE_HELPER_CPP (Mac48Address);
|
|
mathieu@2422
|
30 |
|
|
mathieu@1158
|
31 |
#define ASCII_a (0x41)
|
|
mathieu@1158
|
32 |
#define ASCII_z (0x5a)
|
|
mathieu@1158
|
33 |
#define ASCII_A (0x61)
|
|
mathieu@1158
|
34 |
#define ASCII_Z (0x7a)
|
|
mathieu@1158
|
35 |
#define ASCII_COLON (0x3a)
|
|
mathieu@1158
|
36 |
#define ASCII_ZERO (0x30)
|
|
mathieu@1158
|
37 |
|
|
mathieu@1158
|
38 |
static char
|
|
mathieu@1158
|
39 |
AsciiToLowCase (char c)
|
|
mathieu@1158
|
40 |
{
|
|
mathieu@1158
|
41 |
if (c >= ASCII_a && c <= ASCII_z) {
|
|
mathieu@1158
|
42 |
return c;
|
|
mathieu@1158
|
43 |
} else if (c >= ASCII_A && c <= ASCII_Z) {
|
|
mathieu@1158
|
44 |
return c + (ASCII_a - ASCII_A);
|
|
mathieu@1158
|
45 |
} else {
|
|
mathieu@1158
|
46 |
return c;
|
|
mathieu@1158
|
47 |
}
|
|
mathieu@1158
|
48 |
}
|
|
mathieu@1158
|
49 |
|
|
mathieu@1158
|
50 |
|
|
mathieu@1494
|
51 |
Mac48Address::Mac48Address ()
|
|
mathieu@1158
|
52 |
{
|
|
mathieu@1158
|
53 |
memset (m_address, 0, 6);
|
|
mathieu@1158
|
54 |
}
|
|
mathieu@1494
|
55 |
Mac48Address::Mac48Address (const char *str)
|
|
mathieu@1158
|
56 |
{
|
|
mathieu@1158
|
57 |
int i = 0;
|
|
mathieu@1158
|
58 |
while (*str != 0 && i < 6)
|
|
mathieu@1158
|
59 |
{
|
|
mathieu@1158
|
60 |
uint8_t byte = 0;
|
|
mathieu@1158
|
61 |
while (*str != ASCII_COLON && *str != 0)
|
|
mathieu@1158
|
62 |
{
|
|
mathieu@1158
|
63 |
byte <<= 4;
|
|
mathieu@1158
|
64 |
char low = AsciiToLowCase (*str);
|
|
mathieu@1158
|
65 |
if (low >= ASCII_a)
|
|
mathieu@1158
|
66 |
{
|
|
mathieu@1158
|
67 |
byte |= low - ASCII_a + 10;
|
|
mathieu@1158
|
68 |
}
|
|
mathieu@1158
|
69 |
else
|
|
mathieu@1158
|
70 |
{
|
|
mathieu@1158
|
71 |
byte |= low - ASCII_ZERO;
|
|
mathieu@1158
|
72 |
}
|
|
mathieu@1158
|
73 |
str++;
|
|
mathieu@1158
|
74 |
}
|
|
mathieu@1158
|
75 |
m_address[i] = byte;
|
|
mathieu@1158
|
76 |
i++;
|
|
mathieu@1158
|
77 |
if (*str == 0)
|
|
mathieu@1158
|
78 |
{
|
|
mathieu@1158
|
79 |
break;
|
|
mathieu@1158
|
80 |
}
|
|
mathieu@1158
|
81 |
str++;
|
|
mathieu@1158
|
82 |
}
|
|
mathieu@1158
|
83 |
NS_ASSERT (i == 6);
|
|
mathieu@1158
|
84 |
}
|
|
mathieu@1167
|
85 |
void
|
|
mathieu@1494
|
86 |
Mac48Address::CopyFrom (const uint8_t buffer[6])
|
|
mathieu@1167
|
87 |
{
|
|
mathieu@1167
|
88 |
memcpy (m_address, buffer, 6);
|
|
mathieu@1167
|
89 |
}
|
|
mathieu@1167
|
90 |
void
|
|
mathieu@1494
|
91 |
Mac48Address::CopyTo (uint8_t buffer[6]) const
|
|
mathieu@1167
|
92 |
{
|
|
mathieu@1167
|
93 |
memcpy (buffer, m_address, 6);
|
|
mathieu@1167
|
94 |
}
|
|
mathieu@1167
|
95 |
|
|
mathieu@1173
|
96 |
bool
|
|
mathieu@1494
|
97 |
Mac48Address::IsMatchingType (const Address &address)
|
|
mathieu@1173
|
98 |
{
|
|
mathieu@1173
|
99 |
return address.CheckCompatible (GetType (), 6);
|
|
mathieu@1173
|
100 |
}
|
|
mathieu@1705
|
101 |
Mac48Address::operator Address () const
|
|
mathieu@1205
|
102 |
{
|
|
mathieu@1205
|
103 |
return ConvertTo ();
|
|
mathieu@1205
|
104 |
}
|
|
mathieu@1158
|
105 |
Address
|
|
mathieu@1494
|
106 |
Mac48Address::ConvertTo (void) const
|
|
mathieu@1158
|
107 |
{
|
|
mathieu@1158
|
108 |
return Address (GetType (), m_address, 6);
|
|
mathieu@1158
|
109 |
}
|
|
mathieu@1494
|
110 |
Mac48Address
|
|
mathieu@1494
|
111 |
Mac48Address::ConvertFrom (const Address &address)
|
|
mathieu@1158
|
112 |
{
|
|
mathieu@1159
|
113 |
NS_ASSERT (address.CheckCompatible (GetType (), 6));
|
|
mathieu@1494
|
114 |
Mac48Address retval;
|
|
mathieu@1158
|
115 |
address.CopyTo (retval.m_address);
|
|
mathieu@1158
|
116 |
return retval;
|
|
mathieu@1158
|
117 |
}
|
|
mathieu@1494
|
118 |
Mac48Address
|
|
mathieu@1494
|
119 |
Mac48Address::Allocate (void)
|
|
mathieu@1161
|
120 |
{
|
|
mathieu@1161
|
121 |
static uint64_t id = 0;
|
|
mathieu@1161
|
122 |
id++;
|
|
mathieu@1494
|
123 |
Mac48Address address;
|
|
mathieu@1179
|
124 |
address.m_address[0] = (id >> 40) & 0xff;
|
|
mathieu@1161
|
125 |
address.m_address[1] = (id >> 32) & 0xff;
|
|
mathieu@1161
|
126 |
address.m_address[2] = (id >> 24) & 0xff;
|
|
mathieu@1161
|
127 |
address.m_address[3] = (id >> 16) & 0xff;
|
|
mathieu@1161
|
128 |
address.m_address[4] = (id >> 8) & 0xff;
|
|
mathieu@1161
|
129 |
address.m_address[5] = (id >> 0) & 0xff;
|
|
mathieu@1161
|
130 |
return address;
|
|
mathieu@1161
|
131 |
}
|
|
mathieu@1158
|
132 |
uint8_t
|
|
mathieu@1494
|
133 |
Mac48Address::GetType (void)
|
|
mathieu@1158
|
134 |
{
|
|
mathieu@1158
|
135 |
static uint8_t type = Address::Register ();
|
|
mathieu@1158
|
136 |
return type;
|
|
mathieu@1158
|
137 |
}
|
|
mathieu@1158
|
138 |
|
|
mathieu@1707
|
139 |
bool
|
|
mathieu@1707
|
140 |
Mac48Address::IsBroadcast (void) const
|
|
mathieu@1707
|
141 |
{
|
|
mathieu@1707
|
142 |
return *this == GetBroadcast ();
|
|
mathieu@1707
|
143 |
}
|
|
mathieu@1707
|
144 |
bool
|
|
mathieu@1707
|
145 |
Mac48Address::IsMulticast (void) const
|
|
mathieu@1707
|
146 |
{
|
|
mathieu@3549
|
147 |
uint8_t mcBuf[6];
|
|
mathieu@3549
|
148 |
CopyTo (mcBuf);
|
|
mathieu@3549
|
149 |
mcBuf[3] &= 0x80;
|
|
mathieu@3549
|
150 |
mcBuf[4] = 0;
|
|
mathieu@3549
|
151 |
mcBuf[5] = 0;
|
|
mathieu@3549
|
152 |
Mac48Address prefix;
|
|
mathieu@3549
|
153 |
prefix.CopyFrom (mcBuf);
|
|
mathieu@3549
|
154 |
return prefix == Mac48Address::GetMulticastPrefix ();
|
|
mathieu@3549
|
155 |
}
|
|
mathieu@3549
|
156 |
bool
|
|
mathieu@3549
|
157 |
Mac48Address::IsGroup (void) const
|
|
mathieu@3549
|
158 |
{
|
|
mathieu@1707
|
159 |
return (m_address[0] & 0x01) == 0x01;
|
|
mathieu@1707
|
160 |
}
|
|
mathieu@1707
|
161 |
Mac48Address
|
|
mathieu@1707
|
162 |
Mac48Address::GetBroadcast (void)
|
|
mathieu@1707
|
163 |
{
|
|
mathieu@1707
|
164 |
static Mac48Address broadcast = Mac48Address ("ff:ff:ff:ff:ff:ff");
|
|
mathieu@1707
|
165 |
return broadcast;
|
|
mathieu@1707
|
166 |
}
|
|
mathieu@3549
|
167 |
Mac48Address
|
|
mathieu@3549
|
168 |
Mac48Address::GetMulticastPrefix (void)
|
|
mathieu@3549
|
169 |
{
|
|
mathieu@3549
|
170 |
static Mac48Address multicast = Mac48Address ("01:00:5e:00:00:00");
|
|
mathieu@3549
|
171 |
return multicast;
|
|
mathieu@3549
|
172 |
}
|
|
vincent@3852
|
173 |
Mac48Address
|
|
vincent@3852
|
174 |
Mac48Address::GetMulticast6Prefix (void)
|
|
vincent@3852
|
175 |
{
|
|
vincent@3852
|
176 |
static Mac48Address multicast = Mac48Address ("33:33:00:00:00:00");
|
|
vincent@3852
|
177 |
return multicast;
|
|
vincent@3852
|
178 |
}
|
|
mathieu@3549
|
179 |
Mac48Address
|
|
mathieu@3549
|
180 |
Mac48Address::GetMulticast (Ipv4Address multicastGroup)
|
|
mathieu@3549
|
181 |
{
|
|
mathieu@3549
|
182 |
Mac48Address etherAddr = Mac48Address::GetMulticastPrefix ();
|
|
mathieu@3549
|
183 |
//
|
|
mathieu@3549
|
184 |
// We now have the multicast address in an abstract 48-bit container. We
|
|
mathieu@3549
|
185 |
// need to pull it out so we can play with it. When we're done, we have the
|
|
mathieu@3549
|
186 |
// high order bits in etherBuffer[0], etc.
|
|
mathieu@3549
|
187 |
//
|
|
mathieu@3549
|
188 |
uint8_t etherBuffer[6];
|
|
mathieu@3549
|
189 |
etherAddr.CopyTo (etherBuffer);
|
|
mathieu@3549
|
190 |
|
|
mathieu@3549
|
191 |
//
|
|
mathieu@3549
|
192 |
// Now we need to pull the raw bits out of the Ipv4 destination address.
|
|
mathieu@3549
|
193 |
//
|
|
mathieu@3549
|
194 |
uint8_t ipBuffer[4];
|
|
mathieu@3549
|
195 |
multicastGroup.Serialize (ipBuffer);
|
|
mathieu@3549
|
196 |
|
|
mathieu@3549
|
197 |
//
|
|
mathieu@3549
|
198 |
// RFC 1112 says that an Ipv4 host group address is mapped to an EUI-48
|
|
mathieu@3549
|
199 |
// multicast address by placing the low-order 23-bits of the IP address into
|
|
mathieu@3549
|
200 |
// the low-order 23 bits of the Ethernet multicast address
|
|
mathieu@3549
|
201 |
// 01-00-5E-00-00-00 (hex).
|
|
mathieu@3549
|
202 |
//
|
|
mathieu@3549
|
203 |
etherBuffer[3] |= ipBuffer[1] & 0x7f;
|
|
mathieu@3549
|
204 |
etherBuffer[4] = ipBuffer[2];
|
|
mathieu@3549
|
205 |
etherBuffer[5] = ipBuffer[3];
|
|
mathieu@3549
|
206 |
|
|
mathieu@3549
|
207 |
//
|
|
mathieu@3549
|
208 |
// Now, etherBuffer has the desired ethernet multicast address. We have to
|
|
mathieu@3549
|
209 |
// suck these bits back into the Mac48Address,
|
|
mathieu@3549
|
210 |
//
|
|
mathieu@3549
|
211 |
Mac48Address result;
|
|
mathieu@3549
|
212 |
result.CopyFrom (etherBuffer);
|
|
mathieu@3549
|
213 |
return result;
|
|
mathieu@3549
|
214 |
}
|
|
vincent@3852
|
215 |
Mac48Address Mac48Address::GetMulticast(Ipv6Address addr)
|
|
vincent@3852
|
216 |
{
|
|
vincent@3852
|
217 |
Mac48Address etherAddr = Mac48Address::GetMulticast6Prefix();
|
|
vincent@3852
|
218 |
uint8_t etherBuffer[6];
|
|
vincent@3852
|
219 |
uint8_t ipBuffer[16];
|
|
vincent@3852
|
220 |
|
|
vincent@3852
|
221 |
/* a MAC multicast IPv6 address is like 33:33 and the four low bytes */
|
|
vincent@3852
|
222 |
/* for 2001:db8::2fff:fe11:ac10 => 33:33:FE:11:AC:10 */
|
|
vincent@3852
|
223 |
etherAddr.CopyTo (etherBuffer);
|
|
vincent@3852
|
224 |
addr.Serialize (ipBuffer);
|
|
vincent@3852
|
225 |
|
|
vincent@3852
|
226 |
etherBuffer[2] = ipBuffer[12];
|
|
vincent@3852
|
227 |
etherBuffer[3] = ipBuffer[13];
|
|
vincent@3852
|
228 |
etherBuffer[4] = ipBuffer[14];
|
|
vincent@3852
|
229 |
etherBuffer[5] = ipBuffer[15];
|
|
vincent@3852
|
230 |
|
|
vincent@3852
|
231 |
etherAddr.CopyFrom (etherBuffer);
|
|
vincent@3852
|
232 |
|
|
vincent@3852
|
233 |
return etherAddr;
|
|
vincent@3852
|
234 |
}
|
|
mathieu@2411
|
235 |
|
|
mathieu@1494
|
236 |
bool operator == (const Mac48Address &a, const Mac48Address &b)
|
|
mathieu@1167
|
237 |
{
|
|
mathieu@1707
|
238 |
return memcmp (a.m_address, b.m_address, 6) == 0;
|
|
mathieu@1167
|
239 |
}
|
|
mathieu@1494
|
240 |
bool operator != (const Mac48Address &a, const Mac48Address &b)
|
|
mathieu@1167
|
241 |
{
|
|
mathieu@1167
|
242 |
return ! (a == b);
|
|
mathieu@1167
|
243 |
}
|
|
mathieu@1167
|
244 |
|
|
mathieu@1707
|
245 |
bool operator < (const Mac48Address &a, const Mac48Address &b)
|
|
mathieu@1707
|
246 |
{
|
|
mathieu@1926
|
247 |
uint8_t aP[6];
|
|
mathieu@1926
|
248 |
uint8_t bP[6];
|
|
mathieu@1926
|
249 |
a.CopyTo (aP);
|
|
mathieu@1926
|
250 |
b.CopyTo (bP);
|
|
mathieu@1707
|
251 |
for (uint8_t i = 0; i < 6; i++)
|
|
mathieu@1707
|
252 |
{
|
|
mathieu@1953
|
253 |
if (a.m_address[i] < b.m_address[i])
|
|
mathieu@1707
|
254 |
{
|
|
mathieu@1707
|
255 |
return true;
|
|
mathieu@1707
|
256 |
}
|
|
mathieu@1953
|
257 |
else if (a.m_address[i] > b.m_address[i])
|
|
mathieu@1707
|
258 |
{
|
|
mathieu@1707
|
259 |
return false;
|
|
mathieu@1707
|
260 |
}
|
|
mathieu@1707
|
261 |
}
|
|
mathieu@1707
|
262 |
return false;
|
|
mathieu@1707
|
263 |
}
|
|
mathieu@1707
|
264 |
|
|
mathieu@1707
|
265 |
|
|
mathieu@1494
|
266 |
std::ostream& operator<< (std::ostream& os, const Mac48Address & address)
|
|
mathieu@1167
|
267 |
{
|
|
mathieu@1167
|
268 |
uint8_t ad[6];
|
|
mathieu@1167
|
269 |
address.CopyTo (ad);
|
|
mathieu@1167
|
270 |
|
|
mathieu@1167
|
271 |
os.setf (std::ios::hex, std::ios::basefield);
|
|
mathieu@1262
|
272 |
os.fill('0');
|
|
mathieu@1167
|
273 |
for (uint8_t i=0; i < 5; i++)
|
|
mathieu@1167
|
274 |
{
|
|
mathieu@1167
|
275 |
os << std::setw(2) << (uint32_t)ad[i] << ":";
|
|
mathieu@1167
|
276 |
}
|
|
mathieu@1167
|
277 |
// Final byte not suffixed by ":"
|
|
mathieu@1167
|
278 |
os << std::setw(2) << (uint32_t)ad[5];
|
|
mathieu@1167
|
279 |
os.setf (std::ios::dec, std::ios::basefield);
|
|
mathieu@1262
|
280 |
os.fill(' ');
|
|
mathieu@1167
|
281 |
return os;
|
|
mathieu@1167
|
282 |
}
|
|
mathieu@1167
|
283 |
|
|
mathieu@2954
|
284 |
static uint8_t
|
|
mathieu@2954
|
285 |
AsInt (std::string v)
|
|
mathieu@2411
|
286 |
{
|
|
mathieu@2954
|
287 |
std::istringstream iss;
|
|
mathieu@2954
|
288 |
iss.str (v);
|
|
mathieu@2954
|
289 |
uint32_t retval;
|
|
mathieu@2954
|
290 |
iss >> std::hex >> retval >> std::dec;
|
|
mathieu@2954
|
291 |
return retval;
|
|
mathieu@2954
|
292 |
}
|
|
mathieu@2954
|
293 |
|
|
mathieu@2954
|
294 |
std::istream& operator>> (std::istream& is, Mac48Address & address)
|
|
mathieu@2954
|
295 |
{
|
|
mathieu@2954
|
296 |
std::string v;
|
|
mathieu@2954
|
297 |
is >> v;
|
|
mathieu@2954
|
298 |
|
|
mathieu@2954
|
299 |
std::string::size_type col = 0;
|
|
mathieu@2954
|
300 |
for (uint8_t i = 0; i < 6; ++i)
|
|
mathieu@2954
|
301 |
{
|
|
mathieu@2954
|
302 |
std::string tmp;
|
|
mathieu@2954
|
303 |
std::string::size_type next;
|
|
mathieu@2954
|
304 |
next = v.find (":", col);
|
|
mathieu@2954
|
305 |
if (next == std::string::npos)
|
|
mathieu@2954
|
306 |
{
|
|
mathieu@2954
|
307 |
tmp = v.substr (col, v.size ()-col);
|
|
mathieu@2954
|
308 |
address.m_address[i] = AsInt (tmp);
|
|
mathieu@2954
|
309 |
break;
|
|
mathieu@2954
|
310 |
}
|
|
mathieu@2954
|
311 |
else
|
|
mathieu@2954
|
312 |
{
|
|
mathieu@2954
|
313 |
tmp = v.substr (col, next-col);
|
|
mathieu@2954
|
314 |
address.m_address[i] = AsInt (tmp);
|
|
mathieu@2954
|
315 |
col = next + 1;
|
|
mathieu@2954
|
316 |
}
|
|
mathieu@2954
|
317 |
}
|
|
mathieu@2411
|
318 |
return is;
|
|
mathieu@2411
|
319 |
}
|
|
mathieu@2411
|
320 |
|
|
mathieu@1158
|
321 |
|
|
mathieu@1158
|
322 |
} // namespace ns3
|