PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/s2016/ns3-routing/ns-3/src/node/mac48-address.cc

https://gitlab.com/pmaddi/cs433
C++ | 280 lines | 218 code | 22 blank | 40 comment | 24 complexity | 5b924c0c4183d78cc194261f7ac5ebd4 MD5 | raw 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 "address.h"
  22. #include "ns3/assert.h"
  23. #include <iomanip>
  24. #include <iostream>
  25. #include <string.h>
  26. namespace ns3 {
  27. ATTRIBUTE_HELPER_CPP (Mac48Address);
  28. #define ASCII_a (0x41)
  29. #define ASCII_z (0x5a)
  30. #define ASCII_A (0x61)
  31. #define ASCII_Z (0x7a)
  32. #define ASCII_COLON (0x3a)
  33. #define ASCII_ZERO (0x30)
  34. static char
  35. AsciiToLowCase (char c)
  36. {
  37. if (c >= ASCII_a && c <= ASCII_z) {
  38. return c;
  39. } else if (c >= ASCII_A && c <= ASCII_Z) {
  40. return c + (ASCII_a - ASCII_A);
  41. } else {
  42. return c;
  43. }
  44. }
  45. Mac48Address::Mac48Address ()
  46. {
  47. memset (m_address, 0, 6);
  48. }
  49. Mac48Address::Mac48Address (const char *str)
  50. {
  51. int i = 0;
  52. while (*str != 0 && i < 6)
  53. {
  54. uint8_t byte = 0;
  55. while (*str != ASCII_COLON && *str != 0)
  56. {
  57. byte <<= 4;
  58. char low = AsciiToLowCase (*str);
  59. if (low >= ASCII_a)
  60. {
  61. byte |= low - ASCII_a + 10;
  62. }
  63. else
  64. {
  65. byte |= low - ASCII_ZERO;
  66. }
  67. str++;
  68. }
  69. m_address[i] = byte;
  70. i++;
  71. if (*str == 0)
  72. {
  73. break;
  74. }
  75. str++;
  76. }
  77. NS_ASSERT (i == 6);
  78. }
  79. void
  80. Mac48Address::CopyFrom (const uint8_t buffer[6])
  81. {
  82. memcpy (m_address, buffer, 6);
  83. }
  84. void
  85. Mac48Address::CopyTo (uint8_t buffer[6]) const
  86. {
  87. memcpy (buffer, m_address, 6);
  88. }
  89. bool
  90. Mac48Address::IsMatchingType (const Address &address)
  91. {
  92. return address.CheckCompatible (GetType (), 6);
  93. }
  94. Mac48Address::operator Address () const
  95. {
  96. return ConvertTo ();
  97. }
  98. Address
  99. Mac48Address::ConvertTo (void) const
  100. {
  101. return Address (GetType (), m_address, 6);
  102. }
  103. Mac48Address
  104. Mac48Address::ConvertFrom (const Address &address)
  105. {
  106. NS_ASSERT (address.CheckCompatible (GetType (), 6));
  107. Mac48Address retval;
  108. address.CopyTo (retval.m_address);
  109. return retval;
  110. }
  111. Mac48Address
  112. Mac48Address::Allocate (void)
  113. {
  114. static uint64_t id = 0;
  115. id++;
  116. Mac48Address address;
  117. address.m_address[0] = (id >> 40) & 0xff;
  118. address.m_address[1] = (id >> 32) & 0xff;
  119. address.m_address[2] = (id >> 24) & 0xff;
  120. address.m_address[3] = (id >> 16) & 0xff;
  121. address.m_address[4] = (id >> 8) & 0xff;
  122. address.m_address[5] = (id >> 0) & 0xff;
  123. return address;
  124. }
  125. uint8_t
  126. Mac48Address::GetType (void)
  127. {
  128. static uint8_t type = Address::Register ();
  129. return type;
  130. }
  131. bool
  132. Mac48Address::IsBroadcast (void) const
  133. {
  134. return *this == GetBroadcast ();
  135. }
  136. bool
  137. Mac48Address::IsGroup (void) const
  138. {
  139. return (m_address[0] & 0x01) == 0x01;
  140. }
  141. Mac48Address
  142. Mac48Address::GetBroadcast (void)
  143. {
  144. static Mac48Address broadcast = Mac48Address ("ff:ff:ff:ff:ff:ff");
  145. return broadcast;
  146. }
  147. Mac48Address
  148. Mac48Address::GetMulticastPrefix (void)
  149. {
  150. static Mac48Address multicast = Mac48Address ("01:00:5e:00:00:00");
  151. return multicast;
  152. }
  153. Mac48Address
  154. Mac48Address::GetMulticast6Prefix (void)
  155. {
  156. static Mac48Address multicast = Mac48Address ("33:33:00:00:00:00");
  157. return multicast;
  158. }
  159. Mac48Address
  160. Mac48Address::GetMulticast (Ipv4Address multicastGroup)
  161. {
  162. Mac48Address etherAddr = Mac48Address::GetMulticastPrefix ();
  163. //
  164. // We now have the multicast address in an abstract 48-bit container. We
  165. // need to pull it out so we can play with it. When we're done, we have the
  166. // high order bits in etherBuffer[0], etc.
  167. //
  168. uint8_t etherBuffer[6];
  169. etherAddr.CopyTo (etherBuffer);
  170. //
  171. // Now we need to pull the raw bits out of the Ipv4 destination address.
  172. //
  173. uint8_t ipBuffer[4];
  174. multicastGroup.Serialize (ipBuffer);
  175. //
  176. // RFC 1112 says that an Ipv4 host group address is mapped to an EUI-48
  177. // multicast address by placing the low-order 23-bits of the IP address into
  178. // the low-order 23 bits of the Ethernet multicast address
  179. // 01-00-5E-00-00-00 (hex).
  180. //
  181. etherBuffer[3] |= ipBuffer[1] & 0x7f;
  182. etherBuffer[4] = ipBuffer[2];
  183. etherBuffer[5] = ipBuffer[3];
  184. //
  185. // Now, etherBuffer has the desired ethernet multicast address. We have to
  186. // suck these bits back into the Mac48Address,
  187. //
  188. Mac48Address result;
  189. result.CopyFrom (etherBuffer);
  190. return result;
  191. }
  192. Mac48Address Mac48Address::GetMulticast(Ipv6Address addr)
  193. {
  194. Mac48Address etherAddr = Mac48Address::GetMulticast6Prefix();
  195. uint8_t etherBuffer[6];
  196. uint8_t ipBuffer[16];
  197. /* a MAC multicast IPv6 address is like 33:33 and the four low bytes */
  198. /* for 2001:db8::2fff:fe11:ac10 => 33:33:FE:11:AC:10 */
  199. etherAddr.CopyTo (etherBuffer);
  200. addr.Serialize (ipBuffer);
  201. etherBuffer[2] = ipBuffer[12];
  202. etherBuffer[3] = ipBuffer[13];
  203. etherBuffer[4] = ipBuffer[14];
  204. etherBuffer[5] = ipBuffer[15];
  205. etherAddr.CopyFrom (etherBuffer);
  206. return etherAddr;
  207. }
  208. std::ostream& operator<< (std::ostream& os, const Mac48Address & address)
  209. {
  210. uint8_t ad[6];
  211. address.CopyTo (ad);
  212. os.setf (std::ios::hex, std::ios::basefield);
  213. os.fill('0');
  214. for (uint8_t i=0; i < 5; i++)
  215. {
  216. os << std::setw(2) << (uint32_t)ad[i] << ":";
  217. }
  218. // Final byte not suffixed by ":"
  219. os << std::setw(2) << (uint32_t)ad[5];
  220. os.setf (std::ios::dec, std::ios::basefield);
  221. os.fill(' ');
  222. return os;
  223. }
  224. static uint8_t
  225. AsInt (std::string v)
  226. {
  227. std::istringstream iss;
  228. iss.str (v);
  229. uint32_t retval;
  230. iss >> std::hex >> retval >> std::dec;
  231. return retval;
  232. }
  233. std::istream& operator>> (std::istream& is, Mac48Address & address)
  234. {
  235. std::string v;
  236. is >> v;
  237. std::string::size_type col = 0;
  238. for (uint8_t i = 0; i < 6; ++i)
  239. {
  240. std::string tmp;
  241. std::string::size_type next;
  242. next = v.find (":", col);
  243. if (next == std::string::npos)
  244. {
  245. tmp = v.substr (col, v.size ()-col);
  246. address.m_address[i] = AsInt (tmp);
  247. break;
  248. }
  249. else
  250. {
  251. tmp = v.substr (col, next-col);
  252. address.m_address[i] = AsInt (tmp);
  253. col = next + 1;
  254. }
  255. }
  256. return is;
  257. }
  258. } // namespace ns3