Apache Mesos
net.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_NET_HPP__
14 #define __STOUT_POSIX_NET_HPP__
15 
16 #include <unistd.h>
17 
18 #include <set>
19 #include <string>
20 
21 #include <stout/error.hpp>
22 #include <stout/nothing.hpp>
23 #include <stout/try.hpp>
24 
25 
26 namespace net {
27 
28 inline struct addrinfo createAddrInfo(int socktype, int family, int flags)
29 {
30  struct addrinfo addr;
31  memset(&addr, 0, sizeof(addr));
32  addr.ai_socktype = socktype;
33  addr.ai_family = family;
34  addr.ai_flags |= flags;
35 
36  return addr;
37 }
38 
39 
40 // Returns a Try of the hostname for the provided IP. If the hostname
41 // cannot be resolved, then a string version of the IP address is
42 // returned.
43 //
44 // TODO(benh): Merge with `net::hostname`.
45 inline Try<std::string> getHostname(const IP& ip)
46 {
47  struct sockaddr_storage storage;
48  memset(&storage, 0, sizeof(storage));
49 
50  switch (ip.family()) {
51  case AF_INET: {
52  struct sockaddr_in addr;
53  memset(&addr, 0, sizeof(addr));
54  addr.sin_family = AF_INET;
55  addr.sin_addr = ip.in().get();
56  addr.sin_port = 0;
57 
58  memcpy(&storage, &addr, sizeof(addr));
59  break;
60  }
61  case AF_INET6: {
62  struct sockaddr_in6 addr;
63  memset(&addr, 0, sizeof(addr));
64  addr.sin6_family = AF_INET6;
65  addr.sin6_addr = ip.in6().get();
66  addr.sin6_port = 0;
67 
68  memcpy(&storage, &addr, sizeof(addr));
69  break;
70  }
71  default: {
72  ABORT("Unsupported family type: " + stringify(ip.family()));
73  }
74  }
75 
77  socklen_t length;
78 
79  if (ip.family() == AF_INET) {
80  length = sizeof(struct sockaddr_in);
81  } else if (ip.family() == AF_INET6) {
82  length = sizeof(struct sockaddr_in6);
83  } else {
84  return Error("Unknown address family: " + stringify(ip.family()));
85  }
86 
87  int error = getnameinfo(
88  (struct sockaddr*) &storage,
89  length,
90  hostname,
92  nullptr,
93  0,
94  0);
95 
96  if (error != 0) {
97  return Error(std::string(gai_strerror(error)));
98  }
99 
100  return std::string(hostname);
101 }
102 
103 
104 // Returns a Try of the IP for the provided hostname or an error if no IP is
105 // obtained.
106 inline Try<IP> getIP(const std::string& hostname, int family = AF_UNSPEC)
107 {
108  struct addrinfo hints = createAddrInfo(SOCK_STREAM, family, 0);
109  struct addrinfo* result = nullptr;
110 
111  int error = getaddrinfo(hostname.c_str(), nullptr, &hints, &result);
112 
113  if (error != 0) {
114  return Error(gai_strerror(error));
115  }
116 
117  if (result->ai_addr == nullptr) {
118  freeaddrinfo(result);
119  return Error("No addresses found");
120  }
121 
122  Try<IP> ip = IP::create(*result->ai_addr);
123 
124  if (ip.isError()) {
125  freeaddrinfo(result);
126  return Error("Unsupported family type");
127  }
128 
129  freeaddrinfo(result);
130  return ip.get();
131 }
132 
133 
134 // Returns the names of all the link devices in the system.
136 {
137  struct ifaddrs* ifaddr = nullptr;
138  if (getifaddrs(&ifaddr) == -1) {
139  return ErrnoError();
140  }
141 
142  std::set<std::string> names;
143  for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
144  if (ifa->ifa_name != nullptr) {
145  names.insert(ifa->ifa_name);
146  }
147  }
148 
149  freeifaddrs(ifaddr);
150  return names;
151 }
152 
153 
155 {
156  char host[512];
157 
158  if (gethostname(host, sizeof(host)) < 0) {
159  return ErrnoError();
160  }
161 
162  struct addrinfo hints = createAddrInfo(SOCK_STREAM, AF_UNSPEC, AI_CANONNAME);
163  struct addrinfo* result = nullptr;
164 
165  int error = getaddrinfo(host, nullptr, &hints, &result);
166 
167  if (error != 0) {
168  return Error(gai_strerror(error));
169  }
170 
171  std::string hostname = result->ai_canonname;
172  freeaddrinfo(result);
173 
174  return hostname;
175 }
176 
177 
178 // Returns a `Try` of the result of attempting to set the `hostname`.
179 inline Try<Nothing> setHostname(const std::string& hostname)
180 {
181  if (sethostname(hostname.c_str(), hostname.size()) != 0) {
182  return ErrnoError();
183  }
184 
185  return Nothing();
186 }
187 
188 } // namespace net {
189 
190 #endif // __STOUT_POSIX_NET_HPP__
Try< Nothing > setHostname(const std::string &hostname)
Definition: net.hpp:179
Definition: nothing.hpp:16
Definition: errorbase.hpp:35
#define ABORT(...)
Definition: abort.hpp:40
T & get()&
Definition: try.hpp:73
Try< struct in_addr > in() const
Definition: ip.hpp:124
Definition: check.hpp:33
Definition: errorbase.hpp:49
Try< std::string > getHostname(const IP &ip)
Definition: net.hpp:45
#define MAXHOSTNAMELEN
Definition: windows.hpp:168
Definition: ip.hpp:73
Try< std::set< std::string > > links()
Definition: net.hpp:135
Definition: ip.hpp:70
struct addrinfo createAddrInfo(int socktype, int family, int flags)
Definition: net.hpp:28
Try< std::string > hostname()
Definition: net.hpp:154
#define flags
Definition: decoder.hpp:18
bool isError() const
Definition: try.hpp:71
Try< struct in6_addr > in6() const
Definition: ip.hpp:134
std::string error(const std::string &msg, uint32_t code)
int family() const
Definition: ip.hpp:118
Try< IP > getIP(const std::string &hostname, int family=AF_UNSPEC)
Definition: net.hpp:106
std::string stringify(int flags)
Definition: parse.hpp:33
static Try< IP > create(const struct sockaddr_storage &_storage)
Definition: ip.hpp:454