Evo C++ Library v0.5.1
net_interface.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_net_interface_h
9 #define INCL_net_interface_h
10 
11 #include "substring.h"
12 #include "impl/iter.h"
13 #if defined(_WIN32)
14  #include <stdlib.h>
15  #include <malloc.h>
16  #include <Iphlpapi.h>
17 
18  #pragma comment(lib, "IPHLPAPI.lib")
19 #else
20  #include <ifaddrs.h>
21  #include <net/if.h>
22 #endif
23 
24 namespace evo {
27 
29 
59 public:
60 #if defined(_WIN32)
61  // Windows
62  typedef IP_ADAPTER_ADDRESSES SysItem;
63 #else
64  // Linux/Unix
65  typedef struct ifaddrs SysItem;
66 #endif
67 
69  struct Item {
72  const SysItem* detail;
73  #if defined(_WIN32)
74  // Windows only
75  IP_ADAPTER_UNICAST_ADDRESS* detail_unicast;
76  String detail_name;
77  #endif
78  uint32 scope_id;
79  struct sockaddr* addr;
80  bool active;
81 
83  Item() {
84  detail = NULL;
85  #if defined(_WIN32)
86  detail_unicast = NULL;
87  #endif
88  scope_id = 0;
89  addr = NULL;
90  active = false;
91  }
92 
93  private:
94  // Disable copying
95  Item(const Item&);
96  Item& operator=(const Item&);
97  };
98 
105  NetworkInterfaces(int family=AF_UNSPEC, bool active=true) {
106  ptr_ = NULL;
107  family_ = family;
108  active_ = active;
109  init();
110  }
111 
116  { free(); }
117 
118  // Iterator support types
120  typedef Item IterKey;
121  typedef Item IterItem;
122  typedef uint Size;
126 
127  // Iterator support methods
129  void iterInitMutable()
130  { }
131 
132  const IterItem* iterFirst(IterKey& key) const {
133  const IterItem* result;
134  if (ptr_ == NULL) {
135  key.detail = NULL;
136  result = NULL;
137  } else {
138  result = item_get(key, ptr_);
139  key.detail = ptr_;
140  if (family_ != AF_UNSPEC && (key.addr == NULL || key.addr->sa_family != family_))
141  result = iterNext(key);
142  else
143  result = &key;
144  }
145  return result;
146  }
147 
148  const IterItem* iterNext(IterKey& key) const {
149  for (;;) {
150  if (key.detail != NULL) {
151  if (item_next_address(key)) {
152  if (family_ != AF_UNSPEC && (key.addr == NULL || key.addr->sa_family != family_))
153  continue;
154  return &key;
155  }
156  if (item_next(key)) {
157  item_get(key, key.detail);
158  if (family_ != AF_UNSPEC && (key.addr == NULL || key.addr->sa_family != family_))
159  continue;
160  if (active_ && !item_active(key.detail))
161  continue;
162  return &key;
163  }
164  }
165  break;
166  }
167  return NULL;
168  }
171 private:
172  SysItem* ptr_;
173  int family_;
174  bool active_;
175 
176 #if defined(_WIN32)
177  // Windows
178  void init() {
179  const ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
180  ULONG family = AF_UNSPEC;
181  if (family_ == AF_INET || family_ == AF_INET6)
182  family = family_;
183 
184  const uint MAX_TRIES = 6; // try a few times since required size can change between queries
185  ULONG size = 15360; // 15 KB to start, grow if needed
186  ptr_ = (SysItem*)::malloc(size);
187 
188  ULONG result = GetAdaptersAddresses(family, flags, NULL, ptr_, &size);
189  for (uint i=0; result == ERROR_BUFFER_OVERFLOW && i < MAX_TRIES; ++i) {
190  ptr_ = (SysItem*)::realloc(ptr_, size);
191  result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, ptr_, &size);
192  }
193 
194  if (result != ERROR_SUCCESS)
195  free();
196  }
197 
198  void free() {
199  if (ptr_ != NULL) {
200  ::free(ptr_);
201  ptr_ = NULL;
202  }
203  }
204 
205  static bool item_next_address(Item& item) {
206  if (item.detail_unicast != NULL && (item.detail_unicast = item.detail_unicast->Next) != NULL) {
207  item.addr = item.detail_unicast->Address.lpSockaddr;
208  return true;
209  }
210  return false;
211  }
212 
213  static bool item_next(Item& item) {
214  if (item.detail != NULL)
215  return ((item.detail = item.detail->Next) != NULL);
216  return false;
217  }
218 
219  static bool item_active(const SysItem* ptr)
220  { return ptr->OperStatus & IfOperStatusUp; }
221 
222  static const Item* item_get(Item& item, const SysItem* ptr) {
223  item.detail = ptr;
224  item.id = ptr->AdapterName;
225  item.detail_name.set_win32(ptr->FriendlyName);
226  item.name = item.detail_name;
227  item.scope_id = ptr->Ipv6IfIndex;
228  item.active = item_active(ptr);
229  if ((item.detail_unicast = ptr->FirstUnicastAddress) != NULL)
230  item.addr = item.detail_unicast->Address.lpSockaddr;
231  else
232  item.addr = NULL;
233  return &item;
234  }
235 #else
236  // Linux/Unix
237  void init() {
238  if (::getifaddrs(&ptr_) != 0)
239  ptr_ = NULL;
240  }
241 
242  void free() {
243  if (ptr_ != NULL) {
244  ::freeifaddrs(ptr_);
245  ptr_ = NULL;
246  }
247  }
248 
249  static bool item_next_address(Item&)
250  { return false; }
251 
252  static bool item_next(Item& item) {
253  if (item.detail != NULL)
254  return ((item.detail = item.detail->ifa_next) != NULL);
255  return false;
256  }
257 
258  static bool item_active(const SysItem* ptr)
259  { return ptr->ifa_flags & IFF_UP; }
260 
261  static const Item* item_get(Item& item, const SysItem* ptr) {
262  item.detail = ptr;
263  item.id = ptr->ifa_name;
264  item.name = ptr->ifa_name;
265  item.scope_id = if_nametoindex(ptr->ifa_name);
266  item.addr = ptr->ifa_addr;
267  item.active = item_active(ptr);
268  return &item;
269  }
270 #endif
271 };
272 
274 
275 }
276 #endif
Evo SubString container.
~NetworkInterfaces()
Destructor frees interface data.
Definition: net_interface.h:115
struct sockaddr * addr
Interface address.
Definition: net_interface.h:79
Network iterface item.
Definition: net_interface.h:69
Query network adapter interfaces from OS.
Definition: net_interface.h:58
NetworkInterfaces(int family=AF_UNSPEC, bool active=true)
Constructor queries OS for interfaces.
Definition: net_interface.h:105
String container.
Definition: string.h:674
Evo implementation detail: Container iterators.
Forward iterator.
Definition: iter.h:340
uint32 scope_id
Interface scope ID for IPv6.
Definition: net_interface.h:78
SubString id
Interface ID string (terminated)
Definition: net_interface.h:70
Evo C++ Library namespace.
Definition: alg.h:11
Item()
Constructor.
Definition: net_interface.h:83
IteratorFw< NetworkInterfaces >::Const Iter
Iterator (const) - IteratorFw.
Definition: net_interface.h:125
Reference and access existing string data.
Definition: substring.h:229
const SysItem * detail
Interface system details (system specific)
Definition: net_interface.h:72
bool active
Whether interface is active.
Definition: net_interface.h:80
struct ifaddrs SysItem
System interface item.
Definition: net_interface.h:65
SubString name
Interface name (terminated)
Definition: net_interface.h:71