libtins  4.0
hw_address.h
1 /*
2  * Copyright (c) 2017, Matias Fontanini
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #ifndef TINS_HWADDRESS_H
31 #define TINS_HWADDRESS_H
32 
33 #include <stdint.h>
34 #include <iosfwd>
35 #include <string>
36 #include <cstring>
37 #include <tins/cxxstd.h>
38 #include <tins/macros.h>
39 #if TINS_IS_CXX11
40  // std::hash
41  #include <memory>
42 #endif // TINS_IS_CXX11
43 
44 namespace Tins {
45 namespace Internals {
46 
47 // Defined in hw_address.cpp
51 TINS_API std::string hw_address_to_string(const uint8_t* ptr, size_t count);
52 
53 TINS_API void string_to_hw_address(const std::string& hw_addr, uint8_t* output,
54  size_t output_size);
55 
56 TINS_API bool hw_address_equal_compare(const uint8_t* start1, const uint8_t* end1,
57  const uint8_t* start2);
58 
59 TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
60  const uint8_t* start2, const uint8_t* end2);
61 
62 TINS_API bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
63  const uint8_t* start2, const uint8_t* end2);
64 
68 } // Internals
69 
90 template<size_t n>
91 class HWAddress {
92 public:
96  typedef uint8_t storage_type;
97 
101  typedef storage_type* iterator;
102 
106  typedef const storage_type* const_iterator;
107 
112  static const size_t address_size = n;
113 
117  static const HWAddress<n> broadcast;
118 
134  HWAddress(const storage_type* ptr = 0) {
135  if (ptr) {
136  std::memcpy(buffer_, ptr, address_size);
137  }
138  else {
139  std::memset(buffer_, 0, address_size);
140  }
141  }
142 
154  HWAddress(const std::string& address) {
155  Internals::string_to_hw_address(address, buffer_, n);
156  }
157 
171  template<size_t i>
172  HWAddress(const char (&address)[i]) {
173  Internals::string_to_hw_address(address, buffer_, n);
174  }
175 
188  template<size_t i>
189  HWAddress(const HWAddress<i>& rhs) {
190  size_t copy_threshold = i < n ? i : n;
191  for (size_t index = 0; index < n; ++index) {
192  if (index < copy_threshold) {
193  buffer_[index] = rhs[index];
194  }
195  else {
196  buffer_[index] = storage_type();
197  }
198  }
199  }
200 
207  iterator begin() {
208  return buffer_;
209  }
210 
217  const_iterator begin() const {
218  return buffer_;
219  }
220 
227  iterator end() {
228  return buffer_ + address_size;
229  }
230 
237  const_iterator end() const {
238  return buffer_ + address_size;
239  }
240 
248  bool operator==(const HWAddress& rhs) const {
249  return Internals::hw_address_equal_compare(begin(), end(), rhs.begin());
250  }
251 
259  bool operator!=(const HWAddress& rhs) const {
260  return !(*this == rhs);
261  }
262 
270  bool operator<(const HWAddress& rhs) const {
271  return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end());
272  }
273 
281  bool operator<=(const HWAddress& rhs) const {
282  return !operator>(rhs);
283  }
284 
292  bool operator>(const HWAddress& rhs) const {
293  return Internals::hw_address_gt_compare(begin(), end(), rhs.begin(), rhs.end());
294  }
295 
303  bool operator>=(const HWAddress& rhs) const {
304  return !operator<(rhs);
305  }
306 
313  HWAddress operator&(const HWAddress& mask) const {
314  HWAddress<n> output = *this;
315  for (size_t i = 0; i < n; ++i) {
316  output[i] = output[i] & mask[i];
317  }
318  return output;
319  }
320 
327  HWAddress operator|(const HWAddress& mask) const {
328  HWAddress<n> output = *this;
329  for (size_t i = 0; i < n; ++i) {
330  output[i] = output[i] | mask[i];
331  }
332  return output;
333  }
334 
340  HWAddress<n> output = *this;
341  for (size_t i = 0; i < n; ++i) {
342  output[i] = ~output[i];
343  }
344  return output;
345  }
346 
352  size_t size() const {
353  return address_size;
354  }
355 
359  bool is_broadcast() const {
360  return* this == broadcast;
361  }
362 
366  bool is_multicast() const {
367  return (*begin() & 0x01);
368  }
369 
373  bool is_unicast() const {
374  return !is_broadcast() && !is_multicast();
375  }
376 
382  std::string to_string() const {
383  return Internals::hw_address_to_string(buffer_, size());
384  }
385 
391  storage_type operator[](size_t i) const {
392  return begin()[i];
393  }
394 
400  storage_type& operator[](size_t i) {
401  return begin()[i];
402  }
403 
411  friend std::ostream& operator<<(std::ostream& os, const HWAddress& addr) {
412  return os << addr.to_string();
413  }
414 
430  template<typename OutputIterator>
431  OutputIterator copy(OutputIterator output) const {
432  for (const_iterator iter = begin(); iter != end(); ++iter) {
433  *output++ = *iter;
434  }
435  return output;
436  }
437 private:
438  static HWAddress<n> make_broadcast_address() {
439  // Build a buffer made of n 0xff bytes
440  uint8_t buffer[n];
441  for (size_t i = 0; i < n; ++i) {
442  buffer[i] = 0xff;
443  }
444  return HWAddress<n>(buffer);
445  }
446 
447  storage_type buffer_[n];
448 };
449 
450 template<size_t n>
451 const HWAddress<n> HWAddress<n>::broadcast = make_broadcast_address();
452 
453 } // namespace Tins
454 
455 #if TINS_IS_CXX11
456 namespace std {
457 
458 // Specialization of std::hash for HWAddress
459 template<size_t n>
460 struct hash<Tins::HWAddress<n>> {
461  size_t operator()(const Tins::HWAddress<n>& addr) const {
462  return std::hash<std::string>()(addr.to_string());
463  }
464 };
465 
466 } // namespace std
467 #endif // TINS_IS_CXX11
468 
469 #endif // TINS_HWADDRESS_H
bool is_unicast() const
Indicates whether this is an unicast address.
Definition: hw_address.h:373
HWAddress(const std::string &address)
Constructs an address from a hex-notation address.
Definition: hw_address.h:154
const_iterator begin() const
Retrieves a const iterator pointing to the begining of the address.
Definition: hw_address.h:217
HWAddress operator|(const HWAddress &mask) const
Apply a mask to this address.
Definition: hw_address.h:327
HWAddress operator~() const
not operator
Definition: hw_address.h:339
uint8_t storage_type
The type of the elements stored in the hardware address.
Definition: hw_address.h:96
friend std::ostream & operator<<(std::ostream &os, const HWAddress &addr)
Writes this HWAddress in hex-notation to a std::ostream.
Definition: hw_address.h:411
storage_type operator[](size_t i) const
Retrieves the i-th storage_type in this address.
Definition: hw_address.h:391
Definition: hw_address.h:456
bool operator<=(const HWAddress &rhs) const
Compares this HWAddress for less-than equality.
Definition: hw_address.h:281
iterator begin()
Retrieves an iterator pointing to the begining of the address.
Definition: hw_address.h:207
size_t size() const
Retrieves the size of this address.
Definition: hw_address.h:352
bool operator>(const HWAddress &rhs) const
Compares this HWAddress for greater-than inequality.
Definition: hw_address.h:292
bool is_broadcast() const
Indicates whether this is a broadcast address.
Definition: hw_address.h:359
storage_type & operator[](size_t i)
Retrieves the i-th storage_type in this address.
Definition: hw_address.h:400
Represents a hardware address.
Definition: hw_address.h:91
bool operator!=(const HWAddress &rhs) const
Compares this HWAddress for in-equality.
Definition: hw_address.h:259
HWAddress(const char(&address)[i])
Overload provided basically for string literals.
Definition: hw_address.h:172
The Tins namespace.
Definition: address_range.h:38
bool operator==(const HWAddress &rhs) const
Compares this HWAddress for equality.
Definition: hw_address.h:248
iterator end()
Retrieves an iterator pointing one-past-the-end of the address.
Definition: hw_address.h:227
HWAddress(const HWAddress< i > &rhs)
Copy construct from a HWAddress of length i.
Definition: hw_address.h:189
bool operator<(const HWAddress &rhs) const
Compares this HWAddress for less-than inequality.
Definition: hw_address.h:270
std::string to_string() const
Convert this address to a hex-notation std::string address.
Definition: hw_address.h:382
bool operator>=(const HWAddress &rhs) const
Compares this HWAddress for greater-than equality.
Definition: hw_address.h:303
const_iterator end() const
Retrieves a const iterator pointing one-past-the-end of the address.
Definition: hw_address.h:237
HWAddress(const storage_type *ptr=0)
Constructor from a const storage_type*.
Definition: hw_address.h:134
storage_type * iterator
The random access iterator type.
Definition: hw_address.h:101
static const HWAddress< n > broadcast
The broadcast address.
Definition: hw_address.h:117
OutputIterator copy(OutputIterator output) const
Helper function which copies the address into an output iterator.
Definition: hw_address.h:431
bool is_multicast() const
Indicates whether this is a multicast address.
Definition: hw_address.h:366
HWAddress operator&(const HWAddress &mask) const
Apply a mask to this address.
Definition: hw_address.h:313
const storage_type * const_iterator
Const iterator type.
Definition: hw_address.h:106