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