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