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

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

PF: Implemented GetAdaptersInfo & GetNetworkParams

File size: 15.0 KB
Line 
1/* $Id: iphlpapi.cpp,v 1.6 2002-02-20 11:57:31 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_sizeOfFIXED_INFO(PFIXED_INFO pinfo)
306{
307 PIP_ADDR_STRING pias;
308
309 DWORD dwRequired = sizeof( FIXED_INFO );
310
311 // follow the IP_ADDR_STRING lists
312 pias = &pinfo->DnsServerList;
313 while( pias )
314 {
315 dwRequired += sizeof( IP_ADDR_STRING );
316 pias = pias->Next;
317 }
318 return dwRequired;
319}
320
321static DWORD i_sizeOfIP_ADAPTER_INFO(PIP_ADAPTER_INFO piai)
322{
323 PIP_ADDR_STRING pias;
324
325 // check for sufficient space
326 DWORD dwRequired = sizeof( IP_ADAPTER_INFO );
327
328 // follow the IP_ADDR_STRING lists
329 pias = &piai->IpAddressList;
330 while( pias )
331 {
332 dwRequired += sizeof( IP_ADDR_STRING );
333 pias = pias->Next;
334 }
335
336 pias = &piai->GatewayList;
337 while( pias )
338 {
339 dwRequired += sizeof( IP_ADDR_STRING );
340 pias = pias->Next;
341 }
342
343 pias = &piai->DhcpServer;
344 while( pias )
345 {
346 dwRequired += sizeof( IP_ADDR_STRING );
347 pias = pias->Next;
348 }
349
350 pias = &piai->PrimaryWinsServer;
351 while( pias )
352 {
353 dwRequired += sizeof( IP_ADDR_STRING );
354 pias = pias->Next;
355 }
356
357 pias = &piai->SecondaryWinsServer;
358 while( pias )
359 {
360 dwRequired += sizeof( IP_ADDR_STRING );
361 pias = pias->Next;
362 }
363
364 return dwRequired;
365}
366
367
368//******************************************************************************
369//******************************************************************************
370
371// Note: returns error 50 under NT4 (NOT_SUPPORTED)
372// so we better check out alternative ways, too.
373
374ODINFUNCTION2(DWORD, GetAdaptersInfo,
375 PIP_ADAPTER_INFO, pAdapterInfo,
376 PULONG, pOutBufLen)
377{
378 dprintf(("GetAdaptersInfo API called"));
379 dprintf(("Address passed is %p",pAdapterInfo));
380 if (NULL == pOutBufLen)
381 return ERROR_INVALID_PARAMETER;
382
383 // verify first block of memory to write to
384 if (IsBadWritePtr(pAdapterInfo, 4))
385 return ERROR_INVALID_PARAMETER;
386
387 if (NULL == pipAdapter)
388 {
389 // gather the information and save it
390 i_initializeAdapterInformation();
391 }
392
393 if (NULL == pipAdapter)
394 return ERROR_NO_DATA;
395
396 // OK, just copy over the information as far as possible
397 LONG lSpaceLeft = *pOutBufLen;
398 PBYTE pTarget = (PBYTE)pAdapterInfo;
399 PIP_ADAPTER_INFO pip;
400
401 // calculate overall required buffer size
402 DWORD dwRequiredBuffer = 0;
403
404 for( pip = pipAdapter ; pip ; pip = pip->Next )
405 {
406 // check for sufficient space
407 dwRequiredBuffer += i_sizeOfIP_ADAPTER_INFO(pip);
408 }
409
410 for( pip = pipAdapter ; pip ; pip = pip->Next )
411 {
412 // check for sufficient space
413 DWORD dwRequired = i_sizeOfIP_ADAPTER_INFO(pip);
414
415 if (lSpaceLeft - dwRequired > 0)
416 {
417 lSpaceLeft -= dwRequired;
418
419 // copy over the whole structure hierarchy
420 memcpy(pTarget, pip, sizeof( IP_ADAPTER_INFO ));
421 pTarget += sizeof( IP_ADAPTER_INFO );
422
423 // point to currentIPAddress
424 ((PIP_ADAPTER_INFO)(pTarget))->CurrentIpAddress = &((PIP_ADAPTER_INFO)(pTarget))->IpAddressList;
425 //@@PF Need to fix lots of stuff here
426// i_copyIP_ADDRESS_STRING(&pTarget, &pip->IpAddressList);
427// i_copyIP_ADDRESS_STRING(&pTarget, &pip->GatewayList);
428// i_copyIP_ADDRESS_STRING(&pTarget, &pip->DhcpServer);
429// i_copyIP_ADDRESS_STRING(&pTarget, &pip->PrimaryWinsServer);
430// i_copyIP_ADDRESS_STRING(&pTarget, &pip->SecondaryWinsServer);
431 }
432 else
433 {
434 // return overall size of required buffer
435 *pOutBufLen = dwRequiredBuffer;
436 return ERROR_BUFFER_OVERFLOW;
437 }
438 }
439 return ERROR_SUCCESS;
440}
441
442
443//******************************************************************************
444//******************************************************************************
445ODINFUNCTION2(DWORD, GetNetworkParams,
446 PFIXED_INFO, pFixedInfo,
447 PULONG, pOutBufLen)
448{
449 struct sockaddr_in * sin;
450 FIXED_INFO fi;
451 DWORD memNeeded;
452 PIP_ADDR_STRING dnslist = NULL, pdnslist = NULL;
453
454 // This is dynamically updated info
455 res_init();
456 memset(&fi,0,sizeof(FIXED_INFO));
457
458 dprintf(("GetNetworkParams pFixedInfo:%x pOutBufLen:%d",pFixedInfo,*pOutBufLen));
459
460 gethostname(fi.HostName,128);
461 strcpy(fi.DomainName,_res.defdname);
462
463 // For VPC DNS Servers are pretty much enough for now
464 fi.CurrentDnsServer = &fi.DnsServerList;
465 dnslist = &fi.DnsServerList;
466 pdnslist = dnslist;
467
468 for (int i = 0; i<_res.nscount; i++)
469 {
470 if (!dnslist)
471 {
472 dnslist = (PIP_ADDR_STRING) malloc(sizeof(IP_ADDR_STRING));
473 memset(dnslist,0,sizeof(IP_ADDR_STRING));
474 pdnslist->Next = dnslist;
475 }
476 sin = (struct sockaddr_in *)&_res.nsaddr_list[i];
477 strcpy(dnslist->IpAddress.String,inet_ntoa(sin->sin_addr));
478 dnslist->Context = 0;
479 dprintf(("IPHLPAPI: GetNetworkParams Adding DNS Server %s",inet_ntoa(sin->sin_addr)));
480 pdnslist = dnslist;
481 dnslist = dnslist->Next;
482 }
483 fi.EnableDns = 1;
484 // NodeType (?)
485 memNeeded = i_sizeOfFIXED_INFO(&fi);
486 LONG buflen = *pOutBufLen;
487 PBYTE pTarget = (PBYTE)pFixedInfo;
488 if (((LONG)(buflen - memNeeded)) > 0)
489 {
490 // copy over the whole structure hierarchy
491 memcpy(pTarget, &fi, sizeof( FIXED_INFO ));
492 pTarget += sizeof( FIXED_INFO );
493 i_copyIP_ADDRESS_STRING(&pTarget, &pFixedInfo->DnsServerList,&fi.DnsServerList);
494 }
495 else
496 {
497 // return overall size of required buffer
498 *pOutBufLen = memNeeded;
499 return ERROR_BUFFER_OVERFLOW;
500 }
501
502 //cleanup
503 pdnslist = fi.DnsServerList.Next;
504 while( pdnslist )
505 {
506 dnslist = pdnslist->Next;
507 free(pdnslist);
508 pdnslist = dnslist;
509 }
510
511 return ERROR_SUCCESS;
512}
513//******************************************************************************
514//******************************************************************************
515
516DWORD AddIPAddress(IPAddr Address, // IP address to add
517 IPMask IpMask, // subnet mask for IP address
518 DWORD IfIndex, // index of adapter
519 PULONG NTEContext, // Net Table Entry context
520 PULONG NTEInstance // Net Table Entry Instance
521 );
522// SIOCAIFADDR
523
524DWORD DeleteIPAddress(
525 ULONG NTEContext // net table entry context
526 );
527// SIOCDIFADDR
Note: See TracBrowser for help on using the repository browser.