blob: 34420b3ed6bb4a29b56f7e400b788514b55e8092 [file] [log] [blame]
Junxiao Shi77dcadd2014-10-05 14:40:54 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shie3ef6ee2014-10-05 14:40:54 -07003 * Copyright (c) 2014, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis
Junxiao Shi77dcadd2014-10-05 14:40:54 -070010 *
11 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
12 *
13 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
14 * terms of the GNU Lesser General Public License as published by the Free Software
15 * Foundation, either version 3 of the License, or (at your option) any later version.
16 *
17 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
20 *
21 * You should have received copies of the GNU General Public License and GNU Lesser
22 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
26 */
27
28#include "ethernet.hpp"
29
Davide Pesaventodfb8a612014-11-25 19:14:11 +010030#include <boost/functional/hash.hpp>
31
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010032#include <cstdio>
Davide Pesaventodfe9c6b2014-08-25 21:17:10 +020033#include <ostream>
Junxiao Shi77dcadd2014-10-05 14:40:54 -070034
35namespace ndn {
36namespace util {
37namespace ethernet {
38
Junxiao Shi77dcadd2014-10-05 14:40:54 -070039Address::Address()
40{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010041 fill(0);
Junxiao Shi77dcadd2014-10-05 14:40:54 -070042}
43
44Address::Address(uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6)
45{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010046 data()[0] = a1;
47 data()[1] = a2;
48 data()[2] = a3;
49 data()[3] = a4;
50 data()[4] = a5;
51 data()[5] = a6;
Junxiao Shi77dcadd2014-10-05 14:40:54 -070052}
53
54Address::Address(const uint8_t octets[])
55{
56 std::copy(octets, octets + size(), begin());
57}
58
Junxiao Shi77dcadd2014-10-05 14:40:54 -070059bool
60Address::isBroadcast() const
61{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010062 return *this == getBroadcastAddress();
Junxiao Shi77dcadd2014-10-05 14:40:54 -070063}
64
65bool
66Address::isMulticast() const
67{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010068 return (at(0) & 1) != 0;
Junxiao Shi77dcadd2014-10-05 14:40:54 -070069}
70
71bool
72Address::isNull() const
73{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010074 return *this == Address();
Junxiao Shi77dcadd2014-10-05 14:40:54 -070075}
76
77std::string
78Address::toString(char sep) const
79{
80 char s[18]; // 12 digits + 5 separators + null terminator
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010081
82 // apparently gcc-4.6 does not support the 'hh' type modifier
83 std::snprintf(s, sizeof(s), "%02x%c%02x%c%02x%c%02x%c%02x%c%02x",
84 at(0), sep, at(1), sep, at(2), sep, at(3), sep, at(4), sep, at(5));
85
Junxiao Shi77dcadd2014-10-05 14:40:54 -070086 return std::string(s);
87}
88
89Address
90Address::fromString(const std::string& str)
91{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010092 Address a;
93 unsigned short temp[a.size()];
Junxiao Shi77dcadd2014-10-05 14:40:54 -070094 char sep[5][2]; // 5 * (1 separator char + 1 null terminator)
95 int n = 0; // num of chars read from the input string
96
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010097 // apparently gcc-4.6 does not support the 'hh' type modifier
98 int ret = std::sscanf(str.c_str(), "%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%n",
99 &temp[0], &sep[0][0], &temp[1], &sep[1][0], &temp[2], &sep[2][0],
100 &temp[3], &sep[3][0], &temp[4], &sep[4][0], &temp[5], &n);
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700101
102 if (ret < 11 || static_cast<size_t>(n) != str.length())
103 return Address();
104
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100105 for (size_t i = 0; i < a.size(); ++i)
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700106 {
107 // check that all separators are actually the same char (: or -)
108 if (i < 5 && sep[i][0] != sep[0][0])
109 return Address();
110
111 // check that each value fits into a uint8_t
112 if (temp[i] > 0xFF)
113 return Address();
114
115 a[i] = static_cast<uint8_t>(temp[i]);
116 }
117
118 return a;
119}
120
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100121Address
122getBroadcastAddress()
123{
124 return { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
125}
126
127Address
128getDefaultMulticastAddress()
129{
130 return { 0x01, 0x00, 0x5E, 0x00, 0x17, 0xAA };
131}
132
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700133std::ostream&
134operator<<(std::ostream& o, const Address& a)
135{
136 return o << a.toString();
137}
138
139} // namespace ethernet
140} // namespace util
141} // namespace ndn
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100142
143
144using ndn::util::ethernet::Address;
145
146std::size_t
147std::hash<Address>::operator()(const Address& a) const noexcept
148{
149 return boost::hash_range(a.cbegin(), a.cend());
150}