comparison deps/Platinum/ThirdParty/Neptune/Source/System/Bsd/NptBsdNetwork.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 :: BSD Implementation
4 |
5 | (c) 2001-2005 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
7 |
8 ****************************************************************/
9
10 /*----------------------------------------------------------------------
11 | includes
12 +---------------------------------------------------------------------*/
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/select.h>
16 #include <sys/time.h>
17 #include <sys/ioctl.h>
18 #include <netinet/in.h>
19 #include <net/if.h>
20 //#include <net/if_arp.h>
21 #include <netdb.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <errno.h>
25
26 #include "NptConfig.h"
27 #include "NptTypes.h"
28 #include "NptStreams.h"
29 #include "NptThreads.h"
30 #include "NptNetwork.h"
31 #include "NptUtils.h"
32 #include "NptConstants.h"
33
34 /*----------------------------------------------------------------------
35 | platform adaptation
36 +---------------------------------------------------------------------*/
37 #if !defined(IFHWADDRLEN)
38 #define IFHWADDRLEN 6 // default to 48 bits
39 #endif
40 #if !defined(ARPHRD_ETHER)
41 #define ARPHRD_ETHER 1
42 #endif
43
44 /*----------------------------------------------------------------------
45 | NPT_NetworkInterface::GetNetworkInterfaces
46 +---------------------------------------------------------------------*/
47 NPT_Result
48 NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces)
49 {
50 int net = socket(AF_INET, SOCK_DGRAM, 0);
51
52 // Try to get the config until we have enough memory for it
53 // According to "Unix Network Programming", some implementations
54 // do not return an error when the supplied buffer is too small
55 // so we need to try, increasing the buffer size every time,
56 // until we get the same size twice. We cannot assume success when
57 // the returned size is smaller than the supplied buffer, because
58 // some implementations can return less that the buffer size if
59 // another structure does not fit.
60 unsigned int buffer_size = 4096; // initial guess
61 unsigned int last_size = 0;
62 struct ifconf config;
63 unsigned char* buffer;
64 for (;buffer_size < 16384;) {
65 buffer = new unsigned char[buffer_size];
66 config.ifc_len = buffer_size;
67 config.ifc_buf = (char*)buffer;
68 if (ioctl(net, SIOCGIFCONF, &config) < 0) {
69 if (errno != EINVAL || last_size != 0) {
70 return NPT_ERROR_BASE_UNIX-errno;
71 }
72 } else {
73 if ((unsigned int)config.ifc_len == last_size) {
74 // same size, we can use the buffer
75 break;
76 }
77 // different size, we need to reallocate
78 last_size = config.ifc_len;
79 }
80
81 // supply 256 more bytes more next time around
82 buffer_size += 256;
83 delete[] buffer;
84 }
85
86 unsigned char *entries;
87 for (entries = buffer; entries < buffer+config.ifc_len;) {
88 struct ifreq* entry = (struct ifreq*)entries;
89 // get the size of the addresses
90 unsigned int address_length;
91 #if defined(NPT_CONFIG_HAVE_SOCKADDR_SA_LEN)
92 address_length = sizeof(struct sockaddr) > entry->ifr_addr.sa_len ?
93 sizeof(sockaddr) : entry->ifr_addr.sa_len;
94 #else
95 switch (entry->ifr_addr.sa_family) {
96 #if defined(AF_INET6)
97 case AF_INET6:
98 address_length = sizeof(struct sockaddr_in6);
99 break;
100 #endif // defined(AF_INET6)
101
102 default:
103 address_length = sizeof(struct sockaddr);
104 break;
105 }
106 #endif
107
108 // point to the next entry
109 entries += address_length + sizeof(entry->ifr_name);
110
111 // ignore anything except AF_INET addresses
112 if (entry->ifr_addr.sa_family != AF_INET) {
113 continue;
114 }
115
116 // get detailed info about the interface
117 NPT_Flags flags = 0;
118 #if defined(SIOCGIFFLAGS)
119 struct ifreq query = *entry;
120 if (ioctl(net, SIOCGIFFLAGS, &query) < 0) continue;
121
122 // process the flags
123 if ((query.ifr_flags & IFF_UP) == 0) {
124 // the interface is not up, ignore it
125 continue;
126 }
127 if (query.ifr_flags & IFF_BROADCAST) {
128 flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST;
129 }
130 if (query.ifr_flags & IFF_LOOPBACK) {
131 flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK;
132 }
133 #if defined(IFF_POINTOPOINT)
134 if (query.ifr_flags & IFF_POINTOPOINT) {
135 flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT;
136 }
137 #endif // defined(IFF_POINTOPOINT)
138 if (query.ifr_flags & IFF_PROMISC) {
139 flags |= NPT_NETWORK_INTERFACE_FLAG_PROMISCUOUS;
140 }
141 if (query.ifr_flags & IFF_MULTICAST) {
142 flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST;
143 }
144 #endif // defined(SIOCGIFFLAGS)
145
146 // get the mac address
147 NPT_MacAddress mac;
148 #if defined(SIOCGIFHWADDR)
149 if (ioctl(net, SIOCGIFHWADDR, &query) == 0) {
150 NPT_MacAddress::Type mac_addr_type;
151 unsigned int mac_addr_length = IFHWADDRLEN;
152 switch (query.ifr_addr.sa_family) {
153 #if defined(ARPHRD_ETHER)
154 case ARPHRD_ETHER:
155 mac_addr_type = NPT_MacAddress::TYPE_ETHERNET;
156 break;
157 #endif
158
159 #if defined(ARPHRD_LOOPBACK)
160 case ARPHRD_LOOPBACK:
161 mac_addr_type = NPT_MacAddress::TYPE_LOOPBACK;
162 length = 0;
163 break;
164 #endif
165
166 #if defined(ARPHRD_PPP)
167 case ARPHRD_PPP:
168 mac_addr_type = NPT_MacAddress::TYPE_PPP;
169 mac_addr_length = 0;
170 break;
171 #endif
172
173 #if defined(ARPHRD_IEEE80211)
174 case ARPHRD_IEEE80211:
175 mac_addr_type = NPT_MacAddress::TYPE_IEEE_802_11;
176 break;
177 #endif
178
179 default:
180 mac_addr_type = NPT_MacAddress::TYPE_UNKNOWN;
181 mac_addr_length = sizeof(query.ifr_addr.sa_data);
182 break;
183 }
184
185 mac.SetAddress(mac_addr_type, (const unsigned char*)query.ifr_addr.sa_data, mac_addr_length);
186 }
187 #endif
188
189 // create an interface object
190 NPT_NetworkInterface* interface = new NPT_NetworkInterface(entry->ifr_name, mac, flags);
191
192 // primary address
193 NPT_IpAddress primary_address(ntohl(((struct sockaddr_in*)&entry->ifr_addr)->sin_addr.s_addr));
194
195 // broadcast address
196 NPT_IpAddress broadcast_address;
197 #if defined(SIOCGIFBRDADDR)
198 if (flags & NPT_NETWORK_INTERFACE_FLAG_BROADCAST) {
199 if (ioctl(net, SIOCGIFBRDADDR, &query) == 0) {
200 broadcast_address.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr));
201 }
202 }
203 #endif
204
205 // point to point address
206 NPT_IpAddress destination_address;
207 #if defined(SIOCGIFDSTADDR)
208 if (flags & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT) {
209 if (ioctl(net, SIOCGIFDSTADDR, &query) == 0) {
210 destination_address.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr));
211 }
212 }
213 #endif
214
215 // netmask
216 NPT_IpAddress netmask(0xFFFFFFFF);
217 #if defined(SIOCGIFNETMASK)
218 if (ioctl(net, SIOCGIFNETMASK, &query) == 0) {
219 netmask.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr));
220 }
221 #endif
222
223 // create the interface object
224 NPT_NetworkInterfaceAddress iface_address(
225 primary_address,
226 broadcast_address,
227 destination_address,
228 netmask);
229 interface->AddAddress(iface_address);
230
231 // add the interface to the list
232 interfaces.Add(interface);
233 }
234
235 // free resources
236 delete[] buffer;
237 close(net);
238
239 return NPT_SUCCESS;
240 }