source: trunk/src/iphlpapi/iphlpapi.cpp@ 7981

Last change on this file since 7981 was 7981, checked in by sandervl, 24 years ago

PF: GetNetworkParams bugfixes

File size: 14.3 KB
Line 
1/* $Id: iphlpapi.cpp,v 1.7 2002-02-21 17:01:57 sandervl Exp $ */
2/*
3 * IPHLPAPI library
4 *
5 */
6
7
8/****************************************************************************
9 * includes
10 ****************************************************************************/
11
12
13#include <stdio.h>
14#include <odin.h>
15#include <odinwrap.h>
16#include <os2sel.h>
17
18#include <os2win.h>
19#include <winversion.h>
20
21#include <string.h>
22#include "iphlpapi.h"
23
24#define BSD_SELECT 1
25#define OS2 1
26
27#include <types.h>
28#include <sys\socket.h>
29#include <sys\ioctl.h>
30#include <net\route.h>
31#include <net\if.h>
32#include <net\if_arp.h>
33#ifdef TCPV40HDRS
34#include <netinet\in.h>
35#include <arpa\NAMESER.H>
36#endif
37#include <resolv.h>
38#include <unistd.h>
39
40#include "iphlwrap.h"
41
42#pragma pack(1)
43typedef struct
44{
45 unsigned long IPAddress;
46 unsigned short interfaceNum;
47 unsigned long netmask;
48 unsigned long broadcastAddress;
49} interfaceInformation;
50
51/* Incomplete but will do for us */
52
53#ifndef TCPV40HDRS
54struct ifnet {
55 char *if_name; /* name, e.g. ``en'' or ``lo'' */
56 short if_unit; /* sub-unit for lower level driver */
57 short if_mtu; /* maximum transmission unit */
58};
59#endif
60
61struct ilist {
62 struct ilist *next;
63 unsigned long addr;
64};
65
66struct rlist {
67 struct rlist *next;
68 unsigned long gate;
69 unsigned long net;
70 unsigned long mask;
71 char done;
72};
73
74#pragma pack()
75
76ODINDEBUGCHANNEL(IPHLPAPI-IPHLPAPI)
77
78
79/****************************************************************************
80 * module global variables
81 ****************************************************************************/
82
83static PIP_ADAPTER_INFO pipAdapter = NULL;
84
85
86//******************************************************************************
87//******************************************************************************
88
89void stringIPAddress(char* dst,u_long data)
90{
91 sprintf(dst, "%u.%u.%u.%u",
92 (char)data,
93 (char)(*(((char*)&data) + 1)),
94 (char)(*(((char*)&data) + 2)),
95 (char)(*(((char*)&data) + 3)));
96}
97
98void stringNetmask(char* dst,u_long data)
99{
100 sprintf(dst,"%u.%u.%u.%u",
101 (char)(*(((char*)&data) + 3)),
102 (char)(*(((char*)&data) + 2)),
103 (char)(*(((char*)&data) + 1)),
104 (char)data);
105}
106
107static void i_initializeAdapterInformation(void)
108{
109 unsigned char *p;
110 char iShortName[6];
111 struct rlist * rnode = NULL, * rdef = NULL;
112 PIP_ADAPTER_INFO oldAdapter = NULL,topAdapter = NULL;
113 struct sockaddr_in * sin;
114 struct ifmib ifmibget;
115 int rc,i;
116 char *buffer,*buffer2;
117 struct ifnet *pifnet;
118 short int cInterfaces;
119#ifndef TCPV40HDRS
120 struct ortentry *r;
121#else
122 struct rtentry *r;
123#endif
124
125 // Init Subsystem and open a socket for ioctl() calls
126 sock_init();
127
128 int clientSocket = socket(PF_INET, SOCK_STREAM, 0);
129 dprintf(("IPHLPAPI(Init): Opened socket %d\n", clientSocket));
130
131 // Whole buf minimum size is 65536 and memsets are really needed in other case
132 // we will get garbage in adapter names.
133
134 buffer = (char*)malloc(64 * 1024);
135 memset(buffer, 0, 65536);
136 memset(&ifmibget,0, sizeof(struct ifmib));
137
138 rc = ioctl(clientSocket, SIOSTATIF, (char*)&ifmibget, sizeof(struct ifmib));
139 dprintf(("IPHLPAPI(SIOSTATIF) ioctl returned: %d\n", rc));
140 if (rc == -1)
141 {
142 free(buffer);
143 soclose(clientSocket);
144 return;
145 }
146
147 rc = ioctl(clientSocket, SIOSTATAT, (char*)buffer, 65536);
148 dprintf(("IPHLPAPI(SIOSTATAT) ioctl returned: %d\n", rc));
149 if (rc == -1)
150 {
151 free(buffer);
152 soclose(clientSocket);
153 return;
154 }
155 cInterfaces = *(short int*)buffer;
156 dprintf(("IPHLPAPI Call returned %d interfaces\n", cInterfaces));
157
158 for (int currentInterface = 0; currentInterface < cInterfaces; currentInterface++)
159 {
160 interfaceInformation *ifInfo = (interfaceInformation*)(buffer + 2 + (currentInterface * sizeof(interfaceInformation)));
161 // For now let's dump only lanX and pppX adapters, loopback (?)
162// if (ifInfo->interfaceNum ==9) continue;
163
164 // Allocate and clear mem
165 pipAdapter = (PIP_ADAPTER_INFO)malloc (sizeof (IP_ADAPTER_INFO));
166 memset(pipAdapter, 0, sizeof(IP_ADAPTER_INFO));
167 if (oldAdapter)
168 oldAdapter->Next = pipAdapter;
169
170 pipAdapter->Next = NULL;
171 pipAdapter->ComboIndex = 1;
172 i = ifInfo->interfaceNum;
173 // Gather some other stats
174 dprintf(("IPHLPAPI: interface number: %u\n", ifInfo->interfaceNum));
175
176 if (ifInfo->interfaceNum>=0 && ifInfo->interfaceNum<9) // lanX
177 { strcpy(iShortName,"lan"); iShortName[3] = ifInfo->interfaceNum+48;
178 iShortName[4] = 0;}
179
180 // I do not like this very much, but seems there is no other documented
181 // way
182
183 if (strstr(ifmibget.iftable[i].ifDescr,"back")) // lo
184 strcpy(iShortName,"lo");
185
186 if (strstr(ifmibget.iftable[i].ifDescr,"ace ppp")) // pppX
187 strcpy(iShortName,strstr(ifmibget.iftable[i].ifDescr,"ppp"));
188
189 if (strstr(ifmibget.iftable[i].ifDescr,"ace sl")) // slX
190 strcpy(iShortName,strstr(ifmibget.iftable[i].ifDescr,"sl"));
191
192 if (strstr(ifmibget.iftable[i].ifDescr,"ace dod")) // dodX
193 strcpy(iShortName,strstr(ifmibget.iftable[i].ifDescr,"dod"));
194
195 dprintf(("IPHLPAPI: interface name[%s] : %s\n",iShortName, ifmibget.iftable[i].ifDescr));
196 strcpy(pipAdapter->AdapterName, ifmibget.iftable[i].ifDescr);
197 strcpy(pipAdapter->Description, ifmibget.iftable[i].ifDescr);
198
199 pipAdapter->AddressLength = 6; // MAX address
200 memcpy(pipAdapter->Address,ifmibget.iftable[i].ifPhysAddr,6);
201 pipAdapter->Index = ifmibget.iftable[i].ifIndex;
202 pipAdapter->Type = ifmibget.iftable[i].ifType; // Careful with this (?)
203 pipAdapter->DhcpEnabled = 0; // Also a question
204
205 // TODO: Adapter may support multiple IP addrs
206 IP_ADDR_STRING iasAdapterIP;
207 iasAdapterIP.Next = NULL;
208 stringIPAddress((char*)&iasAdapterIP.IpAddress,ifInfo->IPAddress);
209 stringNetmask((char*)&iasAdapterIP.IpMask,ifInfo->netmask);
210 iasAdapterIP.Context = 0;
211
212 // Now we are going to catch gateways for this interface
213 buffer2 = (char*) malloc(64*1024);
214 memset(buffer2, 0, 65536);
215
216 rc = ioctl(clientSocket, SIOSTATRT, (char*)buffer2, 65536);
217 dprintf(("IPHLPAPI(SIOSTATRT):ioctl returned: %d\n", rc));
218
219 if (rc == -1)
220 {
221 free(buffer);
222 free(buffer2);
223 soclose(clientSocket);
224 // better return nothing than some trash, unwinding and freeing
225 for (topAdapter; pipAdapter; topAdapter = pipAdapter) {
226 pipAdapter = topAdapter -> Next;
227 free(topAdapter);
228 }
229 return;
230 }
231
232 rtentries *routeEntries = (rtentries*)buffer2;
233 p = (unsigned char *)&routeEntries->rttable[0];
234
235 IP_ADDR_STRING iasGateway;
236 memset(&iasGateway,0,sizeof(iasGateway));
237
238 for (int currentRoute = 0; currentRoute < (routeEntries->hostcount+routeEntries->netcount); currentRoute++)
239 {
240 // First check if this route is for our interface
241#ifndef TCPV40HDRS
242 r = (struct ortentry *) (p);
243#else
244 r = (struct rtentry *) (p);
245#endif
246 if (strcmp((const char*)(p + sizeof(struct rtentry)),iShortName)==0)
247 {
248 sin = (struct sockaddr_in *)(&r->rt_dst);
249 if (strcmp(inet_ntoa(sin->sin_addr),"0.0.0.0")==0)
250 {
251 iasGateway.Next = NULL;
252 // TODO : Some systems may have many gateways
253 sin = (struct sockaddr_in *)(&r->rt_gateway);
254 strcpy(iasGateway.IpAddress.String,inet_ntoa(sin->sin_addr));
255 sin = (struct sockaddr_in *)&p[-4];
256 strcpy(iasGateway.IpMask.String,inet_ntoa(sin->sin_addr));
257 iasGateway.Context = 0;
258 }
259 }
260#ifndef TCPV40HDRS
261 p+=sizeof(struct ortentry);
262#else
263 p+=sizeof(struct rtentry);
264#endif
265 p+=strlen((char *)p)+1;
266 }
267
268 memcpy((char*)&pipAdapter->IpAddressList, (char*)&iasAdapterIP, sizeof(iasAdapterIP));
269 pipAdapter->CurrentIpAddress = &pipAdapter->IpAddressList;
270 memcpy((char*)&pipAdapter->GatewayList, (char*)&iasGateway, sizeof(iasGateway));
271 // what about OS/2 DHCP?
272 memset((char*)&pipAdapter->DhcpServer, 0, sizeof( IP_ADDR_STRING ) );
273 pipAdapter->HaveWins = 0;
274 memset((char*)&pipAdapter->PrimaryWinsServer, 0, sizeof( IP_ADDR_STRING ) );
275 memset((char*)&pipAdapter->SecondaryWinsServer, 0, sizeof( IP_ADDR_STRING ) );
276 pipAdapter->LeaseObtained = 0;
277 pipAdapter->LeaseExpires = 0;
278 if (!topAdapter) topAdapter = pipAdapter;
279 oldAdapter = pipAdapter;
280 }
281 pipAdapter = topAdapter;
282
283 // Cleanup
284 if (buffer) free(buffer);
285 if (buffer2) free(buffer2);
286 soclose(clientSocket);
287}
288
289// copy over the whole list and advance the target pointer and correct new list
290static void i_copyIP_ADDRESS_STRING(PBYTE *ppTarget, PIP_ADDR_STRING pstruct,PIP_ADDR_STRING pias)
291{
292 PIP_ADDR_STRING dummy = NULL;
293 // We already have this copied
294 pias = pias -> Next;
295 while (pias)
296 {
297 memcpy(*ppTarget, pias, sizeof( IP_ADDR_STRING ) );
298 pstruct->Next = (PIP_ADDR_STRING) *ppTarget;
299 *ppTarget += sizeof ( IP_ADDR_STRING );
300 pias = pias->Next;
301 pstruct = pstruct->Next;
302 }
303}
304
305static DWORD i_sizeOfIP_ADAPTER_INFO(PIP_ADAPTER_INFO piai)
306{
307 PIP_ADDR_STRING pias;
308
309 // check for sufficient space
310 DWORD dwRequired = sizeof( IP_ADAPTER_INFO );
311
312 // follow the IP_ADDR_STRING lists
313 pias = &piai->IpAddressList;
314 while( pias )
315 {
316 dwRequired += sizeof( IP_ADDR_STRING );
317 pias = pias->Next;
318 }
319
320 pias = &piai->GatewayList;
321 while( pias )
322 {
323 dwRequired += sizeof( IP_ADDR_STRING );
324 pias = pias->Next;
325 }
326
327 pias = &piai->DhcpServer;
328 while( pias )
329 {
330 dwRequired += sizeof( IP_ADDR_STRING );
331 pias = pias->Next;
332 }
333
334 pias = &piai->PrimaryWinsServer;
335 while( pias )
336 {
337 dwRequired += sizeof( IP_ADDR_STRING );
338 pias = pias->Next;
339 }
340
341 pias = &piai->SecondaryWinsServer;
342 while( pias )
343 {
344 dwRequired += sizeof( IP_ADDR_STRING );
345 pias = pias->Next;
346 }
347
348 return dwRequired;
349}
350
351
352//******************************************************************************
353//******************************************************************************
354
355// Note: returns error 50 under NT4 (NOT_SUPPORTED)
356// so we better check out alternative ways, too.
357
358ODINFUNCTION2(DWORD, GetAdaptersInfo,
359 PIP_ADAPTER_INFO, pAdapterInfo,
360 PULONG, pOutBufLen)
361{
362 dprintf(("GetAdaptersInfo API called"));
363 dprintf(("Address passed is %p",pAdapterInfo));
364 if (NULL == pOutBufLen)
365 return ERROR_INVALID_PARAMETER;
366
367 // verify first block of memory to write to
368 if (IsBadWritePtr(pAdapterInfo, 4))
369 return ERROR_INVALID_PARAMETER;
370
371 if (NULL == pipAdapter)
372 {
373 // gather the information and save it
374 i_initializeAdapterInformation();
375 }
376
377 if (NULL == pipAdapter)
378 return ERROR_NO_DATA;
379
380 // OK, just copy over the information as far as possible
381 LONG lSpaceLeft = *pOutBufLen;
382 PBYTE pTarget = (PBYTE)pAdapterInfo;
383 PIP_ADAPTER_INFO pip;
384
385 // calculate overall required buffer size
386 DWORD dwRequiredBuffer = 0;
387
388 for( pip = pipAdapter ; pip ; pip = pip->Next )
389 {
390 // check for sufficient space
391 dwRequiredBuffer += i_sizeOfIP_ADAPTER_INFO(pip);
392 }
393
394 for( pip = pipAdapter ; pip ; pip = pip->Next )
395 {
396 // check for sufficient space
397 DWORD dwRequired = i_sizeOfIP_ADAPTER_INFO(pip);
398
399 if (lSpaceLeft - dwRequired > 0)
400 {
401 lSpaceLeft -= dwRequired;
402
403 // copy over the whole structure hierarchy
404 memcpy(pTarget, pip, sizeof( IP_ADAPTER_INFO ));
405 pTarget += sizeof( IP_ADAPTER_INFO );
406
407 // point to currentIPAddress
408 ((PIP_ADAPTER_INFO)(pTarget))->CurrentIpAddress = &((PIP_ADAPTER_INFO)(pTarget))->IpAddressList;
409 //@@PF Need to fix lots of stuff here
410// i_copyIP_ADDRESS_STRING(&pTarget, &pip->IpAddressList);
411// i_copyIP_ADDRESS_STRING(&pTarget, &pip->GatewayList);
412// i_copyIP_ADDRESS_STRING(&pTarget, &pip->DhcpServer);
413// i_copyIP_ADDRESS_STRING(&pTarget, &pip->PrimaryWinsServer);
414// i_copyIP_ADDRESS_STRING(&pTarget, &pip->SecondaryWinsServer);
415 }
416 else
417 {
418 // return overall size of required buffer
419 *pOutBufLen = dwRequiredBuffer;
420 return ERROR_BUFFER_OVERFLOW;
421 }
422 }
423 return ERROR_SUCCESS;
424}
425
426
427//******************************************************************************
428//******************************************************************************
429ODINFUNCTION2(DWORD, GetNetworkParams,
430 PFIXED_INFO, pFixedInfo,
431 PULONG, pOutBufLen)
432{
433 struct sockaddr_in * sin;
434 PFIXED_INFO fi = pFixedInfo;
435 DWORD memNeeded;
436 PIP_ADDR_STRING dnslist = NULL, pdnslist = NULL;
437 PBYTE pTarget = (PBYTE)pFixedInfo;
438
439 dprintf(("GetNetworkParams pFixedInfo:%x pOutBufLen:%d",pFixedInfo,*pOutBufLen));
440 res_init();
441
442 // Check how much mem we will need
443 memNeeded = sizeof(FIXED_INFO)+_res.nscount*sizeof(IP_ADDR_STRING);
444
445 if (((LONG)(*pOutBufLen - memNeeded)) < 0)
446 {
447 // return overall size of required buffer
448 *pOutBufLen = memNeeded;
449 return ERROR_BUFFER_OVERFLOW;
450 }
451
452 // This is dynamically updated info
453 memset(pFixedInfo,0,memNeeded);
454
455 gethostname(fi->HostName,128);
456 strcpy(fi->DomainName,_res.defdname);
457
458 // For VPC DNS Servers are pretty much enough for now
459 fi->CurrentDnsServer = &fi->DnsServerList;
460 pTarget += sizeof( FIXED_INFO );
461 dnslist = &fi->DnsServerList;
462
463 for (int i = 0; i<_res.nscount; i++)
464 {
465 if (pdnslist) pdnslist->Next = dnslist;
466 sin = (struct sockaddr_in *)&_res.nsaddr_list[i];
467 strcpy(dnslist->IpAddress.String,inet_ntoa(sin->sin_addr));
468 dprintf(("IPHLPAPI: GetNetworkParams Adding DNS Server %s",inet_ntoa(sin->sin_addr)));
469 pdnslist = dnslist;
470 if ( pdnslist == &fi->DnsServerList) dnslist = (PIP_ADDR_STRING)(pTarget + sizeof(IP_ADDR_STRING));
471 else dnslist += sizeof(IP_ADDR_STRING);
472 }
473 fi->EnableDns = 1;
474 return ERROR_SUCCESS;
475}
476//******************************************************************************
477//******************************************************************************
478
479DWORD AddIPAddress(IPAddr Address, // IP address to add
480 IPMask IpMask, // subnet mask for IP address
481 DWORD IfIndex, // index of adapter
482 PULONG NTEContext, // Net Table Entry context
483 PULONG NTEInstance // Net Table Entry Instance
484 );
485// SIOCAIFADDR
486
487DWORD DeleteIPAddress(
488 ULONG NTEContext // net table entry context
489 );
490// SIOCDIFADDR
Note: See TracBrowser for help on using the repository browser.