blob: e9160d9aa8e328f7ed82eee81226b62287626452 [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 {
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
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070054Address::Address(const uint8_t octets[ADDR_LEN])
Junxiao Shi77dcadd2014-10-05 14:40:54 -070055{
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
Alexander Afanasyev52ec6672015-01-22 12:29:02 -080082 // - apparently gcc-4.6 does not support the 'hh' type modifier
83 // - std::snprintf not found in some environments
Alexander Afanasyeve6835fe2017-01-19 20:05:01 -080084 // https://redmine.named-data.net/issues/2299 for more information
Alexander Afanasyev52ec6672015-01-22 12:29:02 -080085 snprintf(s, sizeof(s), "%02x%c%02x%c%02x%c%02x%c%02x%c%02x",
86 at(0), sep, at(1), sep, at(2), sep, at(3), sep, at(4), sep, at(5));
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010087
Junxiao Shi77dcadd2014-10-05 14:40:54 -070088 return std::string(s);
89}
90
91Address
92Address::fromString(const std::string& str)
93{
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010094 Address a;
95 unsigned short temp[a.size()];
Junxiao Shi77dcadd2014-10-05 14:40:54 -070096 char sep[5][2]; // 5 * (1 separator char + 1 null terminator)
97 int n = 0; // num of chars read from the input string
98
Davide Pesavento51dc2ef2014-11-04 20:04:19 +010099 // apparently gcc-4.6 does not support the 'hh' type modifier
100 int ret = std::sscanf(str.c_str(), "%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%1[:-]%2hx%n",
101 &temp[0], &sep[0][0], &temp[1], &sep[1][0], &temp[2], &sep[2][0],
102 &temp[3], &sep[3][0], &temp[4], &sep[4][0], &temp[5], &n);
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700103
104 if (ret < 11 || static_cast<size_t>(n) != str.length())
105 return Address();
106
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100107 for (size_t i = 0; i < a.size(); ++i)
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700108 {
109 // check that all separators are actually the same char (: or -)
110 if (i < 5 && sep[i][0] != sep[0][0])
111 return Address();
112
113 // check that each value fits into a uint8_t
114 if (temp[i] > 0xFF)
115 return Address();
116
117 a[i] = static_cast<uint8_t>(temp[i]);
118 }
119
120 return a;
121}
122
Davide Pesavento51dc2ef2014-11-04 20:04:19 +0100123Address
124getBroadcastAddress()
125{
126 return { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
127}
128
129Address
130getDefaultMulticastAddress()
131{
132 return { 0x01, 0x00, 0x5E, 0x00, 0x17, 0xAA };
133}
134
Junxiao Shi77dcadd2014-10-05 14:40:54 -0700135std::ostream&
136operator<<(std::ostream& o, const Address& a)
137{
138 return o << a.toString();
139}
140
141} // namespace ethernet
142} // namespace util
143} // namespace ndn
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100144
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100145std::size_t
Alexander Afanasyevf2a46222015-09-17 18:01:30 -0700146std::hash<ndn::util::ethernet::Address>::operator()(const ndn::util::ethernet::Address& a) const noexcept
Davide Pesaventodfb8a612014-11-25 19:14:11 +0100147{
148 return boost::hash_range(a.cbegin(), a.cend());
149}