libtins  4.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
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 
65 } // Internals
66 
87 template<size_t n>
88 class HWAddress {
89 public:
93  typedef uint8_t storage_type;
94 
99 
103  typedef const storage_type* const_iterator;
104 
109  static const size_t address_size = n;
110 
114  static const HWAddress<n> broadcast;
115 
131  HWAddress(const storage_type* ptr = 0) {
132  if (ptr) {
133  std::memcpy(buffer_, ptr, address_size);
134  }
135  else {
136  std::memset(buffer_, 0, address_size);
137  }
138  }
139 
151  HWAddress(const std::string& address) {
152  Internals::string_to_hw_address(address, buffer_, n);
153  }
154 
168  template<size_t i>
169  HWAddress(const char (&address)[i]) {
170  Internals::string_to_hw_address(address, buffer_, n);
171  }
172 
185  template<size_t i>
186  HWAddress(const HWAddress<i>& rhs) {
187  size_t copy_threshold = i < n ? i : n;
188  for (size_t index = 0; index < n; ++index) {
189  if (index < copy_threshold) {
190  buffer_[index] = rhs[index];
191  }
192  else {
193  buffer_[index] = storage_type();
194  }
195  }
196  }
197 
205  return buffer_;
206  }
207 
215  return buffer_;
216  }
217 
225  return buffer_ + address_size;
226  }
227 
234  const_iterator end() const {
235  return buffer_ + address_size;
236  }
237 
245  bool operator==(const HWAddress& rhs) const {
246  return Internals::hw_address_equal_compare(begin(), end(), rhs.begin());
247  }
248 
256  bool operator!=(const HWAddress& rhs) const {
257  return !(*this == rhs);
258  }
259 
267  bool operator<(const HWAddress& rhs) const {
268  return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end());
269  }
270 
277  HWAddress operator&(const HWAddress& mask) const {
278  HWAddress<n> output = *this;
279  for (size_t i = 0; i < n; ++i) {
280  output[i] = output[i] & mask[i];
281  }
282  return output;
283  }
284 
290  size_t size() const {
291  return address_size;
292  }
293 
297  bool is_broadcast() const {
298  return* this == broadcast;
299  }
300 
304  bool is_multicast() const {
305  return (*begin() & 0x01);
306  }
307 
311  bool is_unicast() const {
312  return !is_broadcast() && !is_multicast();
313  }
314 
320  std::string to_string() const {
321  return Internals::hw_address_to_string(buffer_, size());
322  }
323 
329  storage_type operator[](size_t i) const {
330  return begin()[i];
331  }
332 
339  return begin()[i];
340  }
341 
349  friend std::ostream& operator<<(std::ostream& os, const HWAddress& addr) {
350  return os << addr.to_string();
351  }
352 
368  template<typename OutputIterator>
369  OutputIterator copy(OutputIterator output) const {
370  for (const_iterator iter = begin(); iter != end(); ++iter) {
371  *output++ = *iter;
372  }
373  return output;
374  }
375 private:
376  static HWAddress<n> make_broadcast_address() {
377  // Build a buffer made of n 0xff bytes
378  uint8_t buffer[n];
379  for (size_t i = 0; i < n; ++i) {
380  buffer[i] = 0xff;
381  }
382  return HWAddress<n>(buffer);
383  }
384 
385  storage_type buffer_[n];
386 };
387 
388 template<size_t n>
389 const HWAddress<n> HWAddress<n>::broadcast = make_broadcast_address();
390 
391 } // namespace Tins
392 
393 #if TINS_IS_CXX11
394 namespace std {
395 
396 // Specialization of std::hash for HWAddress
397 template<size_t n>
398 struct hash<Tins::HWAddress<n>> {
399  size_t operator()(const Tins::HWAddress<n>& addr) const {
400  return std::hash<std::string>()(addr.to_string());
401  }
402 };
403 
404 } // namespace std
405 #endif // TINS_IS_CXX11
406 
407 #endif // TINS_HWADDRESS_H
bool is_unicast() const
Indicates whether this is an unicast address.
Definition: hw_address.h:311
HWAddress(const std::string &address)
Constructs an address from a hex-notation address.
Definition: hw_address.h:151
const_iterator begin() const
Retrieves a const iterator pointing to the begining of the address.
Definition: hw_address.h:214
uint8_t storage_type
The type of the elements stored in the hardware address.
Definition: hw_address.h:93
friend std::ostream & operator<<(std::ostream &os, const HWAddress &addr)
Writes this HWAddress in hex-notation to a std::ostream.
Definition: hw_address.h:349
storage_type operator[](size_t i) const
Retrieves the i-th storage_type in this address.
Definition: hw_address.h:329
iterator begin()
Retrieves an iterator pointing to the begining of the address.
Definition: hw_address.h:204
size_t size() const
Retrieves the size of this address.
Definition: hw_address.h:290
bool is_broadcast() const
Indicates whether this is a broadcast address.
Definition: hw_address.h:297
storage_type & operator[](size_t i)
Retrieves the i-th storage_type in this address.
Definition: hw_address.h:338
Represents a hardware address.
Definition: hw_address.h:88
bool operator!=(const HWAddress &rhs) const
Compares this HWAddress for in-equality.
Definition: hw_address.h:256
HWAddress(const char(&address)[i])
Overload provided basically for string literals.
Definition: hw_address.h:169
bool operator==(const HWAddress &rhs) const
Compares this HWAddress for equality.
Definition: hw_address.h:245
iterator end()
Retrieves an iterator pointing one-past-the-end of the address.
Definition: hw_address.h:224
HWAddress(const HWAddress< i > &rhs)
Copy construct from a HWAddress of length i.
Definition: hw_address.h:186
bool operator<(const HWAddress &rhs) const
Compares this HWAddress for less-than inequality.
Definition: hw_address.h:267
std::string to_string() const
Convert this address to a hex-notation std::string address.
Definition: hw_address.h:320
const_iterator end() const
Retrieves a const iterator pointing one-past-the-end of the address.
Definition: hw_address.h:234
HWAddress(const storage_type *ptr=0)
Constructor from a const storage_type*.
Definition: hw_address.h:131
storage_type * iterator
The random access iterator type.
Definition: hw_address.h:98
static const HWAddress< n > broadcast
The broadcast address.
Definition: hw_address.h:114
static const size_t address_size
Non-member constant indicating the amount of storage_type elements in this address.
Definition: hw_address.h:109
OutputIterator copy(OutputIterator output) const
Helper function which copies the address into an output iterator.
Definition: hw_address.h:369
bool is_multicast() const
Indicates whether this is a multicast address.
Definition: hw_address.h:304
HWAddress operator&(const HWAddress &mask) const
Apply a mask to this address.
Definition: hw_address.h:277
const storage_type * const_iterator
Const iterator type.
Definition: hw_address.h:103