Apache Mesos
mac.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_POSIX_MAC_HPP__
14 #define __STOUT_POSIX_MAC_HPP__
15 
16 #include <ifaddrs.h>
17 
18 #include <sys/types.h>
19 
20 #include <stout/error.hpp>
21 #include <stout/none.hpp>
22 #include <stout/result.hpp>
23 #include <stout/stringify.hpp>
24 
25 
26 // Network utilities.
27 namespace net {
28 
29 // Returns the MAC address of a given link device. The link device is
30 // specified using its name (e.g., eth0). Returns error if the link
31 // device is not found. Returns none if the link device is found, but
32 // does not have a MAC address (e.g., loopback).
33 inline Result<MAC> mac(const std::string& name)
34 {
35  struct ifaddrs* ifaddr = nullptr;
36  if (getifaddrs(&ifaddr) == -1) {
37  return ErrnoError();
38  }
39 
40  // Indicates whether the link device is found or not.
41  bool found = false;
42 
43  for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
44  if (ifa->ifa_name != nullptr && !strcmp(ifa->ifa_name, name.c_str())) {
45  found = true;
46 
47 # if defined(__linux__)
48  if (ifa->ifa_addr != nullptr && ifa->ifa_addr->sa_family == AF_PACKET) {
49  struct sockaddr_ll* link = (struct sockaddr_ll*) ifa->ifa_addr;
50 
51  if (link->sll_halen == 6) {
52  struct ether_addr* addr = (struct ether_addr*) link->sll_addr;
53  MAC mac(addr->ether_addr_octet);
54 
55  // Ignore if the address is 0 so that the results are
56  // consistent on both OSX and Linux.
57  if (stringify(mac) == "00:00:00:00:00:00") {
58  continue;
59  }
60 
61  freeifaddrs(ifaddr);
62  return mac;
63  }
64  }
65 # elif defined(__APPLE__)
66  if (ifa->ifa_addr != nullptr && ifa->ifa_addr->sa_family == AF_LINK) {
67  struct sockaddr_dl* link = (struct sockaddr_dl*) ifa->ifa_addr;
68 
69  if (link->sdl_type == IFT_ETHER && link->sdl_alen == 6) {
70  struct ether_addr* addr = (struct ether_addr*) LLADDR(link);
71  MAC mac(addr->octet);
72 
73  freeifaddrs(ifaddr);
74  return mac;
75  }
76  }
77 # endif
78  }
79  }
80 
81  freeifaddrs(ifaddr);
82 
83  if (!found) {
84  return Error("Cannot find the link device");
85  }
86 
87  return None();
88 }
89 
90 } // namespace net {
91 
92 #endif // __STOUT_POSIX_MAC_HPP__
Definition: errorbase.hpp:36
Definition: errorbase.hpp:50
Definition: check.hpp:30
Definition: ip.hpp:70
Definition: mac.hpp:74
Result< MAC > mac(const std::string &name)
Definition: mac.hpp:33
Definition: none.hpp:27
std::string stringify(int flags)
constexpr const char * name
Definition: shell.hpp:43