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

Last change on this file since 9290 was 9290, checked in by sandervl, 23 years ago

GetNetworkParams: fixed completely broken code to fill in DNS entries

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