IBR-DTNSuite  0.12
Win32LinkManager.cpp
Go to the documentation of this file.
1 /*
2  * Win32LinkManager.cpp
3  *
4  * Created on: 11.10.2012
5  * Author: morgenro
6  */
7 
8 #include "ibrcommon/config.h"
10 #include <sstream>
11 #include <ws2tcpip.h>
12 
13 // Link with Iphlpapi.lib
14 #pragma comment(lib, "IPHLPAPI.lib")
15 
21 namespace ibrcommon
22 {
24  {
25  }
26 
28  {
29  down();
30  }
31  void Win32LinkManager::up() throw()
32  {
33  _lm.start();
34  }
35 
36  void Win32LinkManager::down() throw()
37  {
38  _lm.stop();
39  _lm.join();
40  }
41 
42  void Win32LinkManager::freeAdapterInfo(IP_ADAPTER_ADDRESSES *pAddresses) const
43  {
44  HeapFree(GetProcessHeap(), 0, (pAddresses));
45  }
46 
47  IP_ADAPTER_ADDRESSES* Win32LinkManager::getAdapterInfo() const
48  {
49  PIP_ADAPTER_ADDRESSES pAddresses = NULL;
50 
51  // Set the flags to pass to GetAdaptersAddresses
52  ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
53 
54  // default to unspecified address family (both)
55  ULONG family = AF_UNSPEC;
56 
57  DWORD dwSize = 0;
58  DWORD dwRetVal = 0;
59 
60  // Allocate a 15 KB buffer to start with.
61  ULONG outBufLen = 15000;
62 
63  for (int i = 0; i < 3; i++)
64  {
65  pAddresses = (IP_ADAPTER_ADDRESSES *) HeapAlloc(GetProcessHeap(), 0, (outBufLen));
66  if (pAddresses == NULL) {
67  throw ibrcommon::Exception("Memory allocation failed for IP_ADAPTER_ADDRESSES struct");
68  }
69 
70  dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
71 
72  if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
73  freeAdapterInfo(pAddresses);
74  pAddresses = NULL;
75  } else {
76  break;
77  }
78  }
79 
80  if (dwRetVal == NO_ERROR) return pAddresses;
81 
82  if (pAddresses) freeAdapterInfo(pAddresses);
83 
84  if (dwRetVal == ERROR_NO_DATA) {
85  throw ibrcommon::Exception("No addresses were found for the requested parameters");
86  } else {
87  std::stringstream ss;
88  ss << "Call to GetAdaptersAddresses failed with error: " << dwRetVal;
89  throw ibrcommon::Exception(ss.str());
90  }
91  }
92 
94  {
95  vinterface ret;
96 
97  PIP_ADAPTER_ADDRESSES pAddresses = getAdapterInfo();
98 
99  // find the interface for the given index
100  for (PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; pCurrAddresses->Next != NULL; pCurrAddresses = pCurrAddresses->Next)
101  {
102  if (pCurrAddresses->IfIndex == index) {
103  ret = vinterface(pCurrAddresses->AdapterName);
104  break;
105  }
106  }
107 
108  freeAdapterInfo(pAddresses);
109  return ret;
110  }
111 
112  vaddress Win32LinkManager::getAddress(SOCKET_ADDRESS &sockaddr) const {
113  char str_address[256];
114  DWORD str_length = static_cast<DWORD>(sizeof str_address);
115  if (WSAAddressToString(sockaddr.lpSockaddr, sockaddr.iSockaddrLength, NULL, str_address, &str_length) == 0) {
116  return vaddress(std::string(str_address), "");
117  }
118 
119  throw ibrcommon::Exception("can not convert address into a string");
120  }
121 
122  const std::list<vaddress> Win32LinkManager::getAddressList(const vinterface &iface, const std::string &scope)
123  {
124  std::list<vaddress> ret;
125 
126  PIP_ADAPTER_ADDRESSES pAddresses = getAdapterInfo();
127 
128  for (PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; pCurrAddresses->Next != NULL; pCurrAddresses = pCurrAddresses->Next)
129  {
130  const std::string name(pCurrAddresses->AdapterName);
131 
132  if (iface.toString() == name) {
133  PIP_ADAPTER_UNICAST_ADDRESS pUnicast;
134 
135  for (pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != NULL; pUnicast = pUnicast->Next) {
136  // skip transient addresses
137  if (pUnicast->Flags & IP_ADAPTER_ADDRESS_TRANSIENT) continue;
138 
139  if (scope.length() > 0) {
140  // scope filter only available with IPv6
141  if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6) {
142  // get ipv6 specific address
143  sockaddr_in6 *addr6 = (sockaddr_in6*)pUnicast->Address.lpSockaddr;
144 
145  // if the id is set, then this scope is link-local
146  if (addr6->sin6_scope_id == 0) {
147  if (scope != vaddress::SCOPE_GLOBAL) continue;
148  } else {
149  if (scope != vaddress::SCOPE_LINKLOCAL) continue;
150  }
151  }
152  }
153 
154  // cast to a sockaddr
155  ret.push_back( getAddress(pUnicast->Address) );
156  }
157 
158  break;
159  }
160  }
161 
162  freeAdapterInfo(pAddresses);
163 
164  // return the list of addresses bound to given interface
165  return ret;
166  }
167 
168  std::set<ibrcommon::vinterface> Win32LinkManager::getInterfaces() const
169  {
170  std::set<ibrcommon::vinterface> ret;
171 
172  PIP_ADAPTER_ADDRESSES pAddresses = getAdapterInfo();
173 
174  for (PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; pCurrAddresses->Next != NULL; pCurrAddresses = pCurrAddresses->Next)
175  {
176  const std::string name(pCurrAddresses->AdapterName);
177  const std::wstring friendlyName(pCurrAddresses->FriendlyName);
178 
179  ibrcommon::vinterface iface(name, friendlyName);
180  ret.insert(iface);
181  }
182 
183  freeAdapterInfo(pAddresses);
184 
185  return ret;
186  }
187 
189  {
190  // initialize LinkManager with new listened interface
191  _lm.add(iface);
192 
193  // call super-method
195  }
196 
198  {
199  // call super-method
201 
202  // remove no longer monitored interfaces
203  _lm.remove();
204  }
205 
207  {
208  // call super-method
210 
211  // remove no longer monitored interfaces
212  _lm.remove();
213  }
214 } /* namespace ibrcommon */