Apache Mesos
ip.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_IP_HPP__
14 #define __STOUT_POSIX_IP_HPP__
15 
16 #include <ifaddrs.h>
17 
18 #include <sys/types.h>
19 
20 #include <string>
21 
22 #include <stout/error.hpp>
23 #include <stout/none.hpp>
24 #include <stout/result.hpp>
25 #include <stout/try.hpp>
26 
27 
28 namespace net {
29 
31  const std::string& name,
32  int family)
33 {
34  if (family != AF_INET && family != AF_INET6) {
35  return Error("Unsupported family type: " + stringify(family));
36  }
37 
38  struct ifaddrs* ifaddr = nullptr;
39  if (getifaddrs(&ifaddr) == -1) {
40  return ErrnoError();
41  }
42 
43  // Indicates whether the link device is found or not.
44  bool found = false;
45 
46  for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
47  if (ifa->ifa_name != nullptr && !strcmp(ifa->ifa_name, name.c_str())) {
48  found = true;
49 
50  if (ifa->ifa_addr != nullptr && ifa->ifa_addr->sa_family == family) {
51  IP address = IP::create(*ifa->ifa_addr).get();
52 
53  if (ifa->ifa_netmask != nullptr &&
54  ifa->ifa_netmask->sa_family == family) {
55  IP netmask = IP::create(*ifa->ifa_netmask).get();
56 
57  freeifaddrs(ifaddr);
58 
59  Try<IP::Network> network = IP::Network::create(address, netmask);
60  if (network.isError()) {
61  return Error(network.error());
62  }
63 
64  return network.get();
65  }
66 
67  freeifaddrs(ifaddr);
68 
69  // Note that this is the case where netmask is not specified.
70  // We've seen such cases when VPN is used. In that case, a
71  // default /32 prefix for IPv4 and /64 for IPv6 is used.
72  int prefix = (family == AF_INET ? 32 : 64);
73 
74  Try<IP::Network> network = IP::Network::create(address, prefix);
75  if (network.isError()) {
76  return Error(network.error());
77  }
78 
79  return network.get();
80  }
81  }
82  }
83 
84  freeifaddrs(ifaddr);
85 
86  if (!found) {
87  return Error("Cannot find the link device");
88  }
89 
90  return None();
91 }
92 
93 } // namespace net {
94 
95 #endif // __STOUT_POSIX_IP_HPP__
IP address() const
Definition: ip.hpp:261
Definition: errorbase.hpp:36
T & get()&
Definition: try.hpp:80
Definition: check.hpp:33
Definition: errorbase.hpp:50
Definition: check.hpp:30
Definition: ip.hpp:73
IP netmask() const
Definition: ip.hpp:263
Definition: ip.hpp:70
static Result< Network > fromLinkDevice(const std::string &name, int family)
Definition: ip.hpp:30
static Try error(const E &e)
Definition: try.hpp:43
static Try< Network > create(const IP &address, const IP &netmask)
Definition: ip.hpp:570
Definition: none.hpp:27
bool isError() const
Definition: try.hpp:78
std::string stringify(int flags)
static Try< IP > create(const struct sockaddr_storage &_storage)
Definition: ip.hpp:454
constexpr const char * name
Definition: shell.hpp:41
int prefix() const
Definition: ip.hpp:266