comparison deps/Platinum/ThirdParty/Neptune/Source/System/Win32/NptWin32Network.cpp @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
1 /*****************************************************************
2 |
3 | Neptune - Network :: Winsock Implementation
4 |
5 | (c) 2001-2006 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
7 |
8 ****************************************************************/
9
10 /*----------------------------------------------------------------------
11 | includes
12 +---------------------------------------------------------------------*/
13 #define STRICT
14 #include <winsock2.h>
15 #include <ws2tcpip.h>
16 #include "NptNetwork.h"
17 #include "NptWin32Network.h"
18
19 /*----------------------------------------------------------------------
20 | static initializer
21 +---------------------------------------------------------------------*/
22 NPT_WinsockSystem::NPT_WinsockSystem() {
23 WORD wVersionRequested;
24 WSADATA wsaData;
25 wVersionRequested = MAKEWORD(2, 2);
26 /*wVersionRequested = MAKEWORD(1, 1);*/
27 WSAStartup( wVersionRequested, &wsaData );
28 }
29 NPT_WinsockSystem::~NPT_WinsockSystem() {
30 WSACleanup();
31 }
32 NPT_WinsockSystem NPT_WinsockSystem::Initializer;
33
34 #if defined(_WIN32_WCE)
35 // don't use the SIO_GET_INTERFACE_LIST on Windows CE, it is
36 // hopelessly broken, and will crash your application.
37 #define NPT_NETWORK_USE_IP_HELPER_API
38 #else
39 #define NPT_NETWORK_USE_SIO_GET_INTERFACE_LIST
40 #endif
41
42 #if defined(NPT_NETWORK_USE_SIO_GET_INTERFACE_LIST)
43 /*----------------------------------------------------------------------
44 | NPT_NetworkInterface::GetNetworkInterfaces
45 +---------------------------------------------------------------------*/
46 NPT_Result
47 NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
48 {
49 // create a socket to talk to the TCP/IP stack
50 SOCKET net;
51 if((net = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0)) == INVALID_SOCKET) {
52 return NPT_FAILURE;
53 }
54
55 // get a list of interfaces
56 INTERFACE_INFO query[32]; // get up to 32 interfaces
57 DWORD bytes_returned;
58 int io_result = WSAIoctl(net,
59 SIO_GET_INTERFACE_LIST,
60 NULL, 0,
61 &query, sizeof(query),
62 &bytes_returned,
63 NULL, NULL);
64 if (io_result == SOCKET_ERROR) {
65 closesocket(net);
66 return NPT_FAILURE;
67 }
68
69 // we don't need the socket anymore
70 closesocket(net);
71
72 // Display interface information
73 int interface_count = (bytes_returned/sizeof(INTERFACE_INFO));
74 unsigned int iface_index = 0;
75 for (int i=0; i<interface_count; i++) {
76 SOCKADDR_IN* address;
77 NPT_Flags flags = 0;
78
79 // primary address
80 address = (SOCKADDR_IN*)&query[i].iiAddress;
81 NPT_IpAddress primary_address(ntohl(address->sin_addr.s_addr));
82
83 // netmask
84 address = (SOCKADDR_IN*)&query[i].iiNetmask;
85 NPT_IpAddress netmask(ntohl(address->sin_addr.s_addr));
86
87 // broadcast address
88 address = (SOCKADDR_IN*)&query[i].iiBroadcastAddress;
89 NPT_IpAddress broadcast_address(ntohl(address->sin_addr.s_addr));
90
91 {
92 // broadcast address is incorrect
93 unsigned char addr[4];
94 for(int i=0; i<4; i++) {
95 addr[i] = (primary_address.AsBytes()[i] & netmask.AsBytes()[i]) |
96 ~netmask.AsBytes()[i];
97 }
98 broadcast_address.Set(addr);
99 }
100
101 // ignore interfaces that are not up
102 if (!(query[i].iiFlags & IFF_UP)) {
103 continue;
104 }
105 if (query[i].iiFlags & IFF_BROADCAST) {
106 flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST;
107 }
108 if (query[i].iiFlags & IFF_MULTICAST) {
109 flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST;
110 }
111 if (query[i].iiFlags & IFF_LOOPBACK) {
112 flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK;
113 }
114 if (query[i].iiFlags & IFF_POINTTOPOINT) {
115 flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT;
116 }
117
118 // mac address (no support for this for now)
119 NPT_MacAddress mac;
120
121 // create an interface object
122 char iface_name[5];
123 iface_name[0] = 'i';
124 iface_name[1] = 'f';
125 iface_name[2] = '0'+(iface_index/10);
126 iface_name[3] = '0'+(iface_index%10);
127 iface_name[4] = '\0';
128 NPT_NetworkInterface* iface = new NPT_NetworkInterface(iface_name, mac, flags);
129
130 // set the interface address
131 NPT_NetworkInterfaceAddress iface_address(
132 primary_address,
133 broadcast_address,
134 NPT_IpAddress::Any,
135 netmask);
136 iface->AddAddress(iface_address);
137
138 // add the interface to the list
139 interfaces.Add(iface);
140
141 // increment the index (used for generating the name
142 iface_index++;
143 }
144
145 return NPT_SUCCESS;
146 }
147 #elif defined(NPT_NETWORK_USE_IP_HELPER_API)
148 // Use the IP Helper API
149 #include <iphlpapi.h>
150
151 /*----------------------------------------------------------------------
152 | NPT_NetworkInterface::GetNetworkInterfaces
153 +---------------------------------------------------------------------*/
154 NPT_Result
155 NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
156 {
157 IP_ADAPTER_ADDRESSES* iface_list = NULL;
158 ULONG size = sizeof(IP_ADAPTER_INFO);
159
160 // get the interface table
161 for(;;) {
162 iface_list = (IP_ADAPTER_ADDRESSES*)malloc(size);
163 DWORD result = GetAdaptersAddresses(AF_INET,
164 0,
165 NULL,
166 iface_list, &size);
167 if (result == NO_ERROR) {
168 break;
169 } else {
170 if (result == ERROR_BUFFER_OVERFLOW) {
171 // free and try again
172 free(iface_list);
173 } else {
174 return NPT_FAILURE;
175 }
176 }
177 }
178
179 // iterate over the interfaces
180 for (IP_ADAPTER_ADDRESSES* iface = iface_list; iface; iface = iface->Next) {
181 // skip this interface if it is not up
182 if (iface->OperStatus != IfOperStatusUp) continue;
183
184 // get the interface type and mac address
185 NPT_MacAddress::Type mac_type;
186 switch (iface->IfType) {
187 case IF_TYPE_ETHERNET_CSMACD: mac_type = NPT_MacAddress::TYPE_ETHERNET; break;
188 case IF_TYPE_SOFTWARE_LOOPBACK: mac_type = NPT_MacAddress::TYPE_LOOPBACK; break;
189 case IF_TYPE_PPP: mac_type = NPT_MacAddress::TYPE_PPP; break;
190 default: mac_type = NPT_MacAddress::TYPE_UNKNOWN; break;
191 }
192 NPT_MacAddress mac(mac_type, iface->PhysicalAddress, iface->PhysicalAddressLength);
193
194 // compute interface flags
195 NPT_Flags flags = 0;
196 if (!(iface->Flags & IP_ADAPTER_NO_MULTICAST)) flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST;
197 if (iface->IfType == IF_TYPE_SOFTWARE_LOOPBACK) flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK;
198 if (iface->IfType == IF_TYPE_PPP) flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT;
199
200 // compute the unicast address (only the first one is supported for now)
201 NPT_IpAddress primary_address;
202 if (iface->FirstUnicastAddress) {
203 if (iface->FirstUnicastAddress->Address.lpSockaddr == NULL) continue;
204 if (iface->FirstUnicastAddress->Address.iSockaddrLength != sizeof(SOCKADDR_IN)) continue;
205 SOCKADDR_IN* address = (SOCKADDR_IN*)iface->FirstUnicastAddress->Address.lpSockaddr;
206 if (address->sin_family != AF_INET) continue;
207 primary_address.Set(ntohl(address->sin_addr.s_addr));
208 }
209 NPT_IpAddress broadcast_address; // not supported yet
210 NPT_IpAddress netmask; // not supported yet
211
212 // convert the interface name to UTF-8
213 unsigned int iface_name_length = (unsigned int)wcslen(iface->FriendlyName);
214 char* iface_name = new char[4*iface_name_length+1];
215 int result = WideCharToMultiByte(
216 CP_UTF8, 0, iface->FriendlyName, iface_name_length,
217 iface_name, 4*iface_name_length+1,
218 NULL, NULL);
219 if (result > 0) {
220 iface_name[result] = '\0';
221 } else {
222 iface_name[0] = '\0';
223 }
224
225 // create an interface descriptor
226 NPT_NetworkInterface* iface_object = new NPT_NetworkInterface(iface_name, mac, flags);
227 NPT_NetworkInterfaceAddress iface_address(
228 primary_address,
229 broadcast_address,
230 NPT_IpAddress::Any,
231 netmask);
232 iface_object->AddAddress(iface_address);
233
234 // cleanup
235 delete[] iface_name;
236
237 // add the interface to the list
238 interfaces.Add(iface_object);
239 }
240
241 return NPT_SUCCESS;
242 }
243 #else
244 /*----------------------------------------------------------------------
245 | NPT_NetworkInterface::GetNetworkInterfaces
246 +---------------------------------------------------------------------*/
247 NPT_Result
248 NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>&)
249 {
250 return NPT_SUCCESS;
251 }
252 #endif