blob: 0efdd58f69f4d2c4e58a531b98f4a2ebda2712a8 [file] [log] [blame]
Junxiao Shi77dcadd2014-10-05 14:40:54 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyeve6835fe2017-01-19 20:05:01 -08003 * Copyright (c) 2014-2017 Regents of the University of California,
Davide Pesaventob5f8bcc2017-02-05 17:58:05 -05004 * 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
Alexander Afanasyev52ec6672015-01-22 12:29:02 -080032#include <stdio.h>
Davide Pesaventodfe9c6b2014-08-25 21:17:10 +020033#include <ostream>
Junxiao Shi77dcadd2014-10-05 14:40:54 -070034
35namespace ndn {
Junxiao Shi77dcadd2014-10-05 14:40:54 -070036namespace ethernet {
37
Junxiao Shi77dcadd2014-10-05 14:40:54 -070038Address::Address()
39{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010040 fill(0);
Junxiao Shi77dcadd2014-10-05 14:40:54 -070041}
42
43Address::Address(uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6)
44{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010045 data()[0] = a1;
46 data()[1] = a2;
47 data()[2] = a3;
48 data()[3] = a4;
49 data()[4] = a5;
50 data()[5] = a6;
Junxiao Shi77dcadd2014-10-05 14:40:54 -070051}
52
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070053Address::Address(const uint8_t octets[ADDR_LEN])
Junxiao Shi77dcadd2014-10-05 14:40:54 -070054{
55 std::copy(octets, octets + size(), begin());
56}
57
Junxiao Shi77dcadd2014-10-05 14:40:54 -070058bool
59Address::isBroadcast() const
60{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010061 return *this == getBroadcastAddress();
Junxiao Shi77dcadd2014-10-05 14:40:54 -070062}
63
64bool
65Address::isMulticast() const
66{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010067 return (at(0) & 1) != 0;
Junxiao Shi77dcadd2014-10-05 14:40:54 -070068}
69
70bool
71Address::isNull() const
72{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010073 return *this == Address();
Junxiao Shi77dcadd2014-10-05 14:40:54 -070074}
75
76std::string
77Address::toString(char sep) const
78{
79 char s[18]; // 12 digits + 5 separators + null terminator
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010080
Alexander Afanasyev52ec6672015-01-22 12:29:02 -080081 // - apparently gcc-4.6 does not support the 'hh' type modifier
82 // - std::snprintf not found in some environments
Alexander Afanasyeve6835fe2017-01-19 20:05:01 -080083 // https://redmine.named-data.net/issues/2299 for more information
Alexander Afanasyev52ec6672015-01-22 12:29:02 -080084 snprintf(s, sizeof(s), "%02x%c%02x%c%02x%c%02x%c%02x%c%02x",
85 at(0), sep, at(1), sep, at(2), sep, at(3), sep, at(4), sep, at(5));
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010086
Junxiao Shi77dcadd2014-10-05 14:40:54 -070087 return std::string(s);
88}
89
90Address
91Address::fromString(const std::string& str)
92{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010093 Address a;
94 unsigned short temp[a.size()];
Junxiao Shi77dcadd2014-10-05 14:40:54 -070095 char sep[5][2]; // 5 * (1 separator char + 1 null terminator)
96 int n = 0; // num of chars read from the input string
97
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010098 // apparently gcc-4.6 does not support the 'hh' type modifier
99 int ret = std::sscanf(str.c_str(), "%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%n",
100 &temp[0], &sep[0][0], &temp[1], &sep[1][0], &temp[2], &sep[2][0],
101 &temp[3], &sep[3][0], &temp[4], &sep[4][0], &temp[5], &n);
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700102
103 if (ret < 11 || static_cast<size_t>(n) != str.length())
104 return Address();
105
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100106 for (size_t i = 0; i < a.size(); ++i)
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700107 {
108 // check that all separators are actually the same char (: or -)
109 if (i < 5 && sep[i][0] != sep[0][0])
110 return Address();
111
112 // check that each value fits into a uint8_t
113 if (temp[i] > 0xFF)
114 return Address();
115
116 a[i] = static_cast<uint8_t>(temp[i]);
117 }
118
119 return a;
120}
121
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100122Address
123getBroadcastAddress()
124{
125 return { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
126}
127
128Address
129getDefaultMulticastAddress()
130{
131 return { 0x01, 0x00, 0x5E, 0x00, 0x17, 0xAA };
132}
133
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700134std::ostream&
135operator<<(std::ostream& o, const Address& a)
136{
137 return o << a.toString();
138}
139
140} // namespace ethernet
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700141} // namespace ndn
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100142
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100143std::size_t
Junxiao Shi25467942017-06-30 02:53:14 +0000144std::hash<ndn::ethernet::Address>::operator()(const ndn::ethernet::Address& a) const noexcept
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100145{
146 return boost::hash_range(a.cbegin(), a.cend());
147}