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_WINDOWS_NET_HPP__
14 #define __STOUT_WINDOWS_NET_HPP__
15 
16 #include <set>
17 #include <string>
18 #include <vector>
19 
20 #include <stout/error.hpp>
21 #include <stout/foreach.hpp>
22 #include <stout/nothing.hpp>
23 #include <stout/stringify.hpp>
24 #include <stout/try.hpp>
25 #include <stout/windows.hpp> // For `iphlpapi.h`.
26 
27 #include <stout/windows/os.hpp>
28 
29 
30 namespace net {
31 
32 inline struct addrinfoW createAddrInfo(int socktype, int family, int flags)
33 {
34  struct addrinfoW addr;
35  memset(&addr, 0, sizeof(addr));
36  addr.ai_socktype = socktype;
37  addr.ai_family = family;
38  addr.ai_flags |= flags;
39 
40  return addr;
41 }
42 
43 
44 inline Error GaiError(int error)
45 {
46  return Error(stringify(std::wstring(gai_strerrorW(error))));
47 }
48 
49 
50 // Returns a Try of the hostname for the provided IP. If the hostname
51 // cannot be resolved, then a string version of the IP address is
52 // returned.
53 //
54 // TODO(benh): Merge with `net::hostname`.
55 inline Try<std::string> getHostname(const IP& ip)
56 {
57  struct sockaddr_storage storage;
58  memset(&storage, 0, sizeof(storage));
59 
60  switch (ip.family()) {
61  case AF_INET: {
62  struct sockaddr_in addr;
63  memset(&addr, 0, sizeof(addr));
64  addr.sin_family = AF_INET;
65  addr.sin_addr = ip.in().get();
66  addr.sin_port = 0;
67 
68  memcpy(&storage, &addr, sizeof(addr));
69  break;
70  }
71  case AF_INET6: {
72  struct sockaddr_in6 addr;
73  memset(&addr, 0, sizeof(addr));
74  addr.sin6_family = AF_INET6;
75  addr.sin6_addr = ip.in6().get();
76  addr.sin6_port = 0;
77 
78  memcpy(&storage, &addr, sizeof(addr));
79  break;
80  }
81  default: {
82  ABORT("Unsupported family type: " + stringify(ip.family()));
83  }
84  }
85 
86  wchar_t hostname[MAXHOSTNAMELEN];
87  socklen_t length;
88 
89  if (ip.family() == AF_INET) {
90  length = sizeof(struct sockaddr_in);
91  } else if (ip.family() == AF_INET6) {
92  length = sizeof(struct sockaddr_in6);
93  } else {
94  return Error("Unknown address family: " + stringify(ip.family()));
95  }
96 
97  int error = GetNameInfoW(
98  (struct sockaddr*) &storage,
99  length,
100  hostname,
102  nullptr,
103  0,
104  0);
105 
106  if (error != 0) {
107  return GaiError(error);
108  }
109 
110  return stringify(std::wstring(hostname));
111 }
112 
113 
114 // Returns a Try of the IP for the provided hostname or an error if no IP is
115 // obtained.
116 inline Try<IP> getIP(const std::string& hostname, int family = AF_UNSPEC)
117 {
118  struct addrinfoW hints = createAddrInfo(SOCK_STREAM, family, 0);
119  struct addrinfoW* result = nullptr;
120 
121  int error =
122  GetAddrInfoW(wide_stringify(hostname).data(), nullptr, &hints, &result);
123 
124  if (error != 0) {
125  return GaiError(error);
126  }
127 
128  if (result->ai_addr == nullptr) {
129  FreeAddrInfoW(result);
130  return Error("No addresses found");
131  }
132 
133  Try<IP> ip = IP::create(*result->ai_addr);
134 
135  if (ip.isError()) {
136  FreeAddrInfoW(result);
137  return Error("Unsupported family type");
138  }
139 
140  FreeAddrInfoW(result);
141  return ip.get();
142 }
143 
144 
145 // Returns the names of all the link devices in the system.
146 //
147 // NOTE: On Windows, the device names are GUID's which are not easily
148 // accessible via any command line tools.
149 //
150 // NOTE: This function only returns IPv4 info and does not return any
151 // info about the loopback interface.
153 {
154  DWORD result;
155  ULONG size = 0;
156 
157  // Make an initial call to GetAdaptersInfo to get structure size.
158  if (GetAdaptersInfo(nullptr, &size) != ERROR_BUFFER_OVERFLOW) {
159  return WindowsError("Calling GetAdaptersInfo returned unexpected result");
160  }
161 
162  std::set<std::string> names;
163  std::vector<IP_ADAPTER_INFO> adapter_info(size / sizeof(IP_ADAPTER_INFO));
164  result = GetAdaptersInfo(
165  static_cast<PIP_ADAPTER_INFO>(adapter_info.data()),
166  &size);
167 
168  if (result != NO_ERROR) {
169  return WindowsError(result, "GetAdaptersInfo failed");
170  }
171 
172  foreach (const IP_ADAPTER_INFO& ip_adapter, adapter_info) {
173  names.insert(ip_adapter.AdapterName);
174  }
175 
176  return names;
177 }
178 
179 
180 inline Try<std::string> hostname()
181 {
182  return os::internal::nodename();
183 }
184 
185 
186 // Returns a `Try` of the result of attempting to set the `hostname`.
187 inline Try<Nothing> setHostname(const std::string& hostname)
188 {
189  if (::SetComputerNameW(wide_stringify(hostname).data()) == 0) {
190  return WindowsError();
191  }
192 
193  return Nothing();
194 }
195 
196 } // namespace net {
197 
198 #endif // __STOUT_WINDOWS_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
Try< Bytes > size(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:100
T & get()&
Definition: try.hpp:73
Try< struct in_addr > in() const
Definition: ip.hpp:124
Definition: check.hpp:33
Definition: error.hpp:106
Try< std::string > getHostname(const IP &ip)
Definition: net.hpp:45
#define MAXHOSTNAMELEN
Definition: windows.hpp:168
Definition: ip.hpp:73
Try< std::string > nodename()
Definition: os.hpp:59
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
Error GaiError(int error)
Definition: net.hpp:44
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