xref: /reactos/dll/win32/iphlpapi/ifenum_reactos.c (revision 90be2f4e)
1 /* Copyright (C) 2003 Art Yerkes
2  * A reimplementation of ifenum.c by Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Implementation notes
19  * - Our bretheren use IOCTL_TCP_QUERY_INFORMATION_EX to get information
20  *   from tcpip.sys and IOCTL_TCP_SET_INFORMATION_EX to set info (such as
21  *   the route table).  These ioctls mirror WsControl exactly in usage.
22  * - This iphlpapi does not rely on any reactos-only features.
23  * - This implementation is meant to be largely correct.  I am not, however,
24  *   paying any attention to performance.  It can be done faster, and
25  *   someone should definately optimize this code when speed is more of a
26  *   priority than it is now.
27  *
28  * Edited implementation notes from the original -- Basically edited to add
29  *   information and prune things which are not accurate about this file.
30  * Interface index fun:
31  * - Windows may rely on an index being cleared in the topmost 8 bits in some
32  *   APIs; see GetFriendlyIfIndex and the mention of "backward compatible"
33  *   indexes.  It isn't clear which APIs might fail with non-backward-compatible
34  *   indexes, but I'll keep them bits clear just in case.
35  * FIXME:
36  * - We don't support IPv6 addresses here yet -- I moved the upper edge
37  *   functions into iphlpv6.c (arty)
38  */
39 #include "iphlpapi_private.h"
40 
41 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
42 
43 /* Functions */
44 
45 /* I'm a bit skittish about maintaining this info in memory, as I'd rather
46  * not add any mutex or critical section blockers to these functions.  I've
47  * encountered far too many windows functions that contribute to deadlock
48  * by not announcing themselves. */
interfaceMapInit(void)49 void interfaceMapInit(void)
50 {
51     /* For now, nothing */
52 }
53 
interfaceMapFree(void)54 void interfaceMapFree(void)
55 {
56     /* Ditto. */
57 }
58 
tdiGetMibForIfEntity(HANDLE tcpFile,TDIEntityID * ent,IFEntrySafelySized * entry)59 NTSTATUS tdiGetMibForIfEntity
60 ( HANDLE tcpFile, TDIEntityID *ent, IFEntrySafelySized *entry ) {
61     TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
62     NTSTATUS status = STATUS_SUCCESS;
63     DWORD returnSize;
64 
65     WARN("TdiGetMibForIfEntity(tcpFile %p,entityId %p)\n",
66            tcpFile, ent->tei_instance);
67 
68     req.ID.toi_class                = INFO_CLASS_PROTOCOL;
69     req.ID.toi_type                 = INFO_TYPE_PROVIDER;
70     req.ID.toi_id                   = IF_MIB_STATS_ID;
71     req.ID.toi_entity               = *ent;
72 
73     status = DeviceIoControl( tcpFile,
74                               IOCTL_TCP_QUERY_INFORMATION_EX,
75                               &req,
76                               sizeof(req),
77                               entry,
78                               sizeof(*entry),
79                               &returnSize,
80                               NULL );
81 
82     if(!status)
83     {
84             WARN("IOCTL Failed\n");
85             return STATUS_UNSUCCESSFUL;
86     }
87 
88     TRACE("TdiGetMibForIfEntity() => {\n"
89            "  if_index ....................... %x\n"
90            "  if_type ........................ %x\n"
91            "  if_mtu ......................... %d\n"
92            "  if_speed ....................... %x\n"
93            "  if_physaddrlen ................. %d\n",
94            entry->ent.if_index,
95            entry->ent.if_type,
96            entry->ent.if_mtu,
97            entry->ent.if_speed,
98            entry->ent.if_physaddrlen);
99     TRACE("  if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n"
100            "  if_descr ....................... %*s\n",
101            entry->ent.if_physaddr[0] & 0xff,
102            entry->ent.if_physaddr[1] & 0xff,
103            entry->ent.if_physaddr[2] & 0xff,
104            entry->ent.if_physaddr[3] & 0xff,
105            entry->ent.if_physaddr[4] & 0xff,
106            entry->ent.if_physaddr[5] & 0xff,
107            entry->ent.if_descrlen,
108            entry->ent.if_descr);
109     TRACE("} status %08x\n",status);
110 
111     return STATUS_SUCCESS;
112 }
113 
isInterface(TDIEntityID * if_maybe)114 BOOL isInterface( TDIEntityID *if_maybe ) {
115     return
116         if_maybe->tei_entity == IF_ENTITY;
117 }
118 
isLoopback(HANDLE tcpFile,TDIEntityID * loop_maybe)119 BOOL isLoopback( HANDLE tcpFile, TDIEntityID *loop_maybe ) {
120     IFEntrySafelySized entryInfo;
121     NTSTATUS status;
122 
123     status = tdiGetMibForIfEntity( tcpFile,
124                                    loop_maybe,
125                                    &entryInfo );
126 
127     return NT_SUCCESS(status) &&
128            (entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK);
129 }
130 
hasArp(HANDLE tcpFile,TDIEntityID * arp_maybe)131 BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe ) {
132     TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
133     NTSTATUS status = STATUS_SUCCESS;
134     DWORD returnSize, type;
135 
136     req.ID.toi_class                = INFO_CLASS_GENERIC;
137     req.ID.toi_type                 = INFO_TYPE_PROVIDER;
138     req.ID.toi_id                   = ENTITY_TYPE_ID;
139     req.ID.toi_entity.tei_entity    = AT_ENTITY;
140     req.ID.toi_entity.tei_instance  = arp_maybe->tei_instance;
141 
142     status = DeviceIoControl( tcpFile,
143                               IOCTL_TCP_QUERY_INFORMATION_EX,
144                               &req,
145                               sizeof(req),
146                               &type,
147                               sizeof(type),
148                               &returnSize,
149                               NULL );
150     if( !NT_SUCCESS(status) ) return FALSE;
151 
152     /* AT_ARP corresponds to an individual TDI entity type */
153     return (type == AT_ARP);
154 }
155 
getInterfaceInfoSet(HANDLE tcpFile,IFInfo ** infoSet,PDWORD numInterfaces)156 static NTSTATUS getInterfaceInfoSet( HANDLE tcpFile,
157                                      IFInfo **infoSet,
158                                      PDWORD numInterfaces ) {
159     DWORD numEntities;
160     TDIEntityID *entIDSet = NULL;
161     NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entIDSet, &numEntities );
162     IFInfo *infoSetInt = 0;
163     int curInterf = 0, i;
164 
165     if (!NT_SUCCESS(status)) {
166         ERR("getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status);
167         return status;
168     }
169 
170     infoSetInt = HeapAlloc( GetProcessHeap(), 0,
171                             sizeof(IFInfo) * numEntities );
172 
173     if( infoSetInt ) {
174         for( i = 0; i < numEntities; i++ ) {
175             if( isInterface( &entIDSet[i] ) ) {
176                 infoSetInt[curInterf].entity_id = entIDSet[i];
177                 status = tdiGetMibForIfEntity
178                     ( tcpFile,
179                       &entIDSet[i],
180                       &infoSetInt[curInterf].if_info );
181                 TRACE("tdiGetMibForIfEntity: %08x\n", status);
182                 if( NT_SUCCESS(status) ) {
183                     DWORD numAddrs;
184                     IPAddrEntry *addrs;
185                     TDIEntityID ip_ent;
186                     int j;
187 
188                     status = getNthIpEntity( tcpFile, curInterf, &ip_ent );
189                     if( NT_SUCCESS(status) )
190                         status = tdiGetIpAddrsForIpEntity
191                             ( tcpFile, &ip_ent, &addrs, &numAddrs );
192                     for( j = 0; NT_SUCCESS(status) && j < numAddrs; j++ ) {
193                         TRACE("ADDR %d: index %d (target %d)\n", j, addrs[j].iae_index, infoSetInt[curInterf].if_info.ent.if_index);
194                         if( addrs[j].iae_index ==
195                             infoSetInt[curInterf].if_info.ent.if_index ) {
196                             memcpy( &infoSetInt[curInterf].ip_addr,
197                                     &addrs[j],
198                                     sizeof( addrs[j] ) );
199                             curInterf++;
200                             break;
201                         }
202                     }
203                     if ( NT_SUCCESS(status) )
204                         tdiFreeThingSet(addrs);
205                 }
206             }
207         }
208 
209         tdiFreeThingSet(entIDSet);
210 
211         if (NT_SUCCESS(status)) {
212             *infoSet = infoSetInt;
213             *numInterfaces = curInterf;
214         } else {
215             HeapFree(GetProcessHeap(), 0, infoSetInt);
216         }
217 
218         return status;
219     } else {
220         tdiFreeThingSet(entIDSet);
221         return STATUS_INSUFFICIENT_RESOURCES;
222     }
223 }
224 
getNumInterfacesInt(BOOL onlyNonLoopback)225 static DWORD getNumInterfacesInt(BOOL onlyNonLoopback)
226 {
227     DWORD numEntities, numInterfaces = 0;
228     TDIEntityID *entitySet;
229     HANDLE tcpFile;
230     NTSTATUS status;
231     int i;
232 
233     status = openTcpFile( &tcpFile, FILE_READ_DATA );
234 
235     if( !NT_SUCCESS(status) ) {
236         WARN("getNumInterfaces: failed %08x\n", status );
237         return 0;
238     }
239 
240     status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
241 
242     if( !NT_SUCCESS(status) ) {
243         WARN("getNumInterfaces: failed %08x\n", status );
244         closeTcpFile( tcpFile );
245         return 0;
246     }
247 
248     for( i = 0; i < numEntities; i++ ) {
249         if( isInterface( &entitySet[i] ) &&
250             (!onlyNonLoopback || !isLoopback( tcpFile, &entitySet[i] )) )
251             numInterfaces++;
252     }
253 
254     TRACE("getNumInterfaces: success: %d %d %08x\n",
255            onlyNonLoopback, numInterfaces, status );
256 
257     closeTcpFile( tcpFile );
258 
259     tdiFreeThingSet( entitySet );
260 
261     return numInterfaces;
262 }
263 
getNumInterfaces(void)264 DWORD getNumInterfaces(void)
265 {
266     return getNumInterfacesInt( FALSE );
267 }
268 
getNumNonLoopbackInterfaces(void)269 DWORD getNumNonLoopbackInterfaces(void)
270 {
271     return getNumInterfacesInt( TRUE );
272 }
273 
getNthInterfaceEntity(HANDLE tcpFile,DWORD index,TDIEntityID * ent)274 DWORD getNthInterfaceEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) {
275     DWORD numEntities = 0;
276     DWORD numInterfaces = 0;
277     TDIEntityID *entitySet = 0;
278     NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
279     int i;
280 
281     if( !NT_SUCCESS(status) )
282         return status;
283 
284     for( i = 0; i < numEntities; i++ ) {
285         if( isInterface( &entitySet[i] ) ) {
286             if( numInterfaces == index ) break;
287             else numInterfaces++;
288         }
289     }
290 
291     TRACE("Index %d is entity #%d - %04x:%08x\n", index, i,
292            entitySet[i].tei_entity, entitySet[i].tei_instance );
293 
294     if( numInterfaces == index && i < numEntities ) {
295         memcpy( ent, &entitySet[i], sizeof(*ent) );
296         tdiFreeThingSet( entitySet );
297         return STATUS_SUCCESS;
298     } else {
299         tdiFreeThingSet( entitySet );
300         return STATUS_UNSUCCESSFUL;
301     }
302 }
303 
getInterfaceInfoByIndex(HANDLE tcpFile,DWORD index,IFInfo * info)304 NTSTATUS getInterfaceInfoByIndex( HANDLE tcpFile, DWORD index, IFInfo *info ) {
305     IFInfo *ifInfo;
306     DWORD numInterfaces;
307     NTSTATUS status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces );
308     int i;
309 
310     if( NT_SUCCESS(status) )
311     {
312         for( i = 0; i < numInterfaces; i++ ) {
313             if( ifInfo[i].if_info.ent.if_index == index ) {
314                 memcpy( info, &ifInfo[i], sizeof(*info) );
315                 break;
316             }
317         }
318 
319         HeapFree(GetProcessHeap(), 0, ifInfo);
320 
321         return i < numInterfaces ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
322     }
323 
324     return status;
325 }
326 
getInterfaceInfoByName(HANDLE tcpFile,char * name,IFInfo * info)327 NTSTATUS getInterfaceInfoByName( HANDLE tcpFile, char *name, IFInfo *info ) {
328     IFInfo *ifInfo;
329     DWORD numInterfaces;
330     int i;
331     NTSTATUS status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces );
332 
333     if( NT_SUCCESS(status) )
334     {
335         for( i = 0; i < numInterfaces; i++ ) {
336             if( !strncmp((PCHAR)ifInfo[i].if_info.ent.if_descr, name, ifInfo[i].if_info.ent.if_descrlen) ) {
337                 memcpy( info, &ifInfo[i], sizeof(*info) );
338                 break;
339             }
340         }
341 
342         HeapFree(GetProcessHeap(), 0,ifInfo);
343 
344         return i < numInterfaces ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
345     }
346 
347     return status;
348 }
349 
350 /* Note that the result of this operation must be freed later */
351 
getInterfaceNameByIndex(DWORD index)352 const char *getInterfaceNameByIndex(DWORD index)
353 {
354     IFInfo ifInfo;
355     HANDLE tcpFile;
356     char *interfaceName = NULL;
357     NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
358 
359     if( NT_SUCCESS(status) ) {
360         status = getInterfaceInfoByIndex( tcpFile, index, &ifInfo );
361 
362         if( NT_SUCCESS(status) ) {
363             interfaceName = HeapAlloc( GetProcessHeap(), 0,
364                                        ifInfo.if_info.ent.if_descrlen + 1 );
365             if( interfaceName ) {
366               memcpy(interfaceName, ifInfo.if_info.ent.if_descr, ifInfo.if_info.ent.if_descrlen);
367               interfaceName[ifInfo.if_info.ent.if_descrlen] = '\0';
368             }
369         }
370 
371         closeTcpFile( tcpFile );
372     }
373 
374     return interfaceName;
375 }
376 
consumeInterfaceName(const char * name)377 void consumeInterfaceName(const char *name) {
378     HeapFree( GetProcessHeap(), 0, (char *)name );
379 }
380 
getInterfaceIndexByName(const char * name,PDWORD index)381 DWORD getInterfaceIndexByName(const char *name, PDWORD index)
382 {
383     IFInfo ifInfo;
384     HANDLE tcpFile;
385     NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
386 
387     if( NT_SUCCESS(status) ) {
388         status = getInterfaceInfoByName( tcpFile, (char *)name, &ifInfo );
389 
390         if( NT_SUCCESS(status) ) {
391             *index = ifInfo.if_info.ent.if_index;
392         }
393 
394         closeTcpFile( tcpFile );
395     }
396 
397     return status;
398 }
399 
getInterfaceIndexTableInt(BOOL nonLoopbackOnly)400 InterfaceIndexTable *getInterfaceIndexTableInt( BOOL nonLoopbackOnly ) {
401   DWORD numInterfaces, curInterface = 0;
402   int i;
403   IFInfo *ifInfo;
404   InterfaceIndexTable *ret = 0;
405   HANDLE tcpFile;
406   NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
407 
408   if( NT_SUCCESS(status) ) {
409       status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces );
410 
411       TRACE("InterfaceInfoSet: %08x, %04x:%08x\n",
412              status,
413              ifInfo->entity_id.tei_entity,
414              ifInfo->entity_id.tei_instance);
415 
416       if( NT_SUCCESS(status) ) {
417           ret = (InterfaceIndexTable *)
418               calloc(1,
419                      sizeof(InterfaceIndexTable) +
420                      (numInterfaces - 1) * sizeof(DWORD));
421 
422           if (ret) {
423               ret->numAllocated = numInterfaces;
424               TRACE("NumInterfaces = %d\n", numInterfaces);
425 
426               for( i = 0; i < numInterfaces; i++ ) {
427                   TRACE("Examining interface %d\n", i);
428                   if( !nonLoopbackOnly ||
429                       !isLoopback( tcpFile, &ifInfo[i].entity_id ) ) {
430                       TRACE("Interface %d matches (%d)\n", i, curInterface);
431                       ret->indexes[curInterface++] =
432                           ifInfo[i].if_info.ent.if_index;
433                   }
434               }
435 
436               ret->numIndexes = curInterface;
437           }
438 
439           tdiFreeThingSet( ifInfo );
440       }
441       closeTcpFile( tcpFile );
442   }
443 
444   return ret;
445 }
446 
getInterfaceIndexTable(void)447 InterfaceIndexTable *getInterfaceIndexTable(void) {
448     return getInterfaceIndexTableInt( FALSE );
449 }
450 
getNonLoopbackInterfaceIndexTable(void)451 InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void) {
452     return getInterfaceIndexTableInt( TRUE );
453 }
454 
getInterfaceIPAddrByName(const char * name)455 DWORD getInterfaceIPAddrByName(const char *name)
456 {
457     return INADDR_ANY;
458 }
459 
getIPAddrEntryForIf(HANDLE tcpFile,char * name,DWORD index,IFInfo * ifInfo)460 NTSTATUS getIPAddrEntryForIf(HANDLE tcpFile,
461                              char *name,
462                              DWORD index,
463                              IFInfo *ifInfo) {
464     NTSTATUS status =
465         name ?
466         getInterfaceInfoByName( tcpFile, name, ifInfo ) :
467         getInterfaceInfoByIndex( tcpFile, index, ifInfo );
468 
469     if (!NT_SUCCESS(status)) {
470         ERR("getIPAddrEntryForIf returning %lx\n", status);
471     }
472 
473     return status;
474 }
475 
getAddrByIndexOrName(char * name,DWORD index,IPHLPAddrType addrType)476 DWORD getAddrByIndexOrName( char *name, DWORD index, IPHLPAddrType addrType ) {
477     IFInfo ifInfo;
478     HANDLE tcpFile;
479     NTSTATUS status = STATUS_SUCCESS;
480     DWORD addrOut = INADDR_ANY;
481 
482     status = openTcpFile( &tcpFile, FILE_READ_DATA );
483 
484     if( NT_SUCCESS(status) ) {
485         status = getIPAddrEntryForIf( tcpFile, name, index, &ifInfo );
486         if( NT_SUCCESS(status) ) {
487             switch( addrType ) {
488             case IPAAddr:  addrOut = ifInfo.ip_addr.iae_addr; break;
489             case IPABcast: addrOut = ifInfo.ip_addr.iae_bcastaddr; break;
490             case IPAMask:  addrOut = ifInfo.ip_addr.iae_mask; break;
491             case IFMtu:    addrOut = ifInfo.if_info.ent.if_mtu; break;
492             case IFStatus: addrOut = ifInfo.if_info.ent.if_operstatus; break;
493             }
494         }
495         closeTcpFile( tcpFile );
496     }
497 
498     return addrOut;
499 }
500 
getInterfaceIPAddrByIndex(DWORD index)501 DWORD getInterfaceIPAddrByIndex(DWORD index) {
502     return getAddrByIndexOrName( 0, index, IPAAddr );
503 }
504 
getInterfaceBCastAddrByName(const char * name)505 DWORD getInterfaceBCastAddrByName(const char *name) {
506     return getAddrByIndexOrName( (char *)name, 0, IPABcast );
507 }
508 
getInterfaceBCastAddrByIndex(DWORD index)509 DWORD getInterfaceBCastAddrByIndex(DWORD index) {
510     return getAddrByIndexOrName( 0, index, IPABcast );
511 }
512 
getInterfaceMaskByName(const char * name)513 DWORD getInterfaceMaskByName(const char *name) {
514     return getAddrByIndexOrName( (char *)name, 0, IPAMask );
515 }
516 
getInterfaceMaskByIndex(DWORD index)517 DWORD getInterfaceMaskByIndex(DWORD index) {
518     return getAddrByIndexOrName( 0, index, IPAMask );
519 }
520 
getInterfacePhysicalFromInfo(IFInfo * info,PDWORD len,PBYTE addr,PDWORD type)521 void getInterfacePhysicalFromInfo( IFInfo *info,
522                                    PDWORD len, PBYTE addr, PDWORD type ) {
523     *len = info->if_info.ent.if_physaddrlen;
524     memcpy( addr, info->if_info.ent.if_physaddr, *len );
525     *type = info->if_info.ent.if_type;
526 }
527 
getInterfacePhysicalByName(const char * name,PDWORD len,PBYTE addr,PDWORD type)528 DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
529                                  PDWORD type)
530 {
531     HANDLE tcpFile;
532     IFInfo info;
533     NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
534 
535     if( NT_SUCCESS(status) ) {
536         status = getInterfaceInfoByName( tcpFile, (char *)name, &info );
537         if( NT_SUCCESS(status) )
538             getInterfacePhysicalFromInfo( &info, len, addr, type );
539         closeTcpFile( tcpFile );
540     }
541 
542     return status;
543 }
544 
getInterfacePhysicalByIndex(DWORD index,PDWORD len,PBYTE addr,PDWORD type)545 DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
546  PDWORD type)
547 {
548     HANDLE tcpFile;
549     IFInfo info;
550     NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
551 
552     if( NT_SUCCESS(status) ) {
553         status = getInterfaceInfoByIndex( tcpFile, index, &info );
554         if( NT_SUCCESS(status) )
555             getInterfacePhysicalFromInfo( &info, len, addr, type );
556         closeTcpFile( tcpFile );
557     }
558 
559     return status;
560 }
561 
getInterfaceMtuByName(const char * name,PDWORD mtu)562 DWORD getInterfaceMtuByName(const char *name, PDWORD mtu) {
563     *mtu = getAddrByIndexOrName( (char *)name, 0, IFMtu );
564     return STATUS_SUCCESS;
565 }
566 
getInterfaceMtuByIndex(DWORD index,PDWORD mtu)567 DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu) {
568     *mtu = getAddrByIndexOrName( 0, index, IFMtu );
569     return STATUS_SUCCESS;
570 }
571 
getInterfaceStatusByName(const char * name,PDWORD status)572 DWORD getInterfaceStatusByName(const char *name, PDWORD status) {
573     *status = getAddrByIndexOrName( (char *)name, 0, IFStatus );
574     return STATUS_SUCCESS;
575 }
576 
getInterfaceStatusByIndex(DWORD index,PDWORD status)577 DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status)
578 {
579     *status = getAddrByIndexOrName( 0, index, IFStatus );
580     return STATUS_SUCCESS;
581 }
582 
getInterfaceEntryByName(const char * name,PMIB_IFROW entry)583 DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
584 {
585     HANDLE tcpFile;
586     IFInfo info;
587     NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
588 
589     TRACE("Called.\n");
590 
591     if( NT_SUCCESS(status) ) {
592         status = getInterfaceInfoByName( tcpFile, (char *)name, &info );
593 
594         if( NT_SUCCESS(status) ) {
595             memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN],
596                     &info.if_info,
597                     sizeof(info.if_info) );
598         }
599 
600         TRACE("entry->bDescr = %s\n", entry->bDescr);
601 
602         closeTcpFile( tcpFile );
603     }
604 
605     return status;
606 }
607 
getInterfaceEntryByIndex(DWORD index,PMIB_IFROW entry)608 DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry)
609 {
610     HANDLE tcpFile;
611     IFInfo info;
612     NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA );
613 
614     TRACE("Called.\n");
615 
616     if( NT_SUCCESS(status) ) {
617         status = getInterfaceInfoByIndex( tcpFile, index, &info );
618 
619         if( NT_SUCCESS(status) ) {
620             memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN],
621                     &info.if_info,
622                     sizeof(info.if_info) );
623         }
624 
625         closeTcpFile( tcpFile );
626     }
627 
628     return status;
629 }
630 
toIPAddressString(unsigned int addr,char string[16])631 char *toIPAddressString(unsigned int addr, char string[16])
632 {
633     struct in_addr iAddr;
634 
635     iAddr.s_addr = addr;
636 
637     if (string)
638         strncpy(string, inet_ntoa(iAddr), 16);
639 
640     return inet_ntoa(iAddr);
641 }
642 
addIPAddress(IPAddr Address,IPMask Mask,DWORD IfIndex,PULONG NteContext,PULONG NteInstance)643 NTSTATUS addIPAddress( IPAddr Address, IPMask Mask, DWORD IfIndex,
644                        PULONG NteContext, PULONG NteInstance )
645 {
646   HANDLE tcpFile;
647   NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA );
648   IP_SET_DATA Data;
649   IO_STATUS_BLOCK Iosb;
650 
651   TRACE("Called.\n");
652 
653   if( !NT_SUCCESS(status) ) return status;
654 
655   Data.NteContext = IfIndex;
656   Data.NewAddress = Address;
657   Data.NewNetmask = Mask;
658 
659   status = NtDeviceIoControlFile( tcpFile,
660                                   NULL,
661                                   NULL,
662                                   NULL,
663                                   &Iosb,
664                                   IOCTL_SET_IP_ADDRESS,
665                                   &Data,
666                                   sizeof(Data),
667                                   &Data,
668                                   sizeof(Data) );
669 
670   closeTcpFile( tcpFile );
671 
672   if( NT_SUCCESS(status) ) {
673       *NteContext = Iosb.Information;
674       *NteInstance = Data.NewAddress;
675   }
676 
677   if (!NT_SUCCESS(status)) {
678       ERR("addIPAddress for if %d returning 0x%lx\n", IfIndex, status);
679   }
680 
681   return status;
682 
683 }
684 
deleteIpAddress(ULONG NteContext)685 NTSTATUS deleteIpAddress( ULONG NteContext )
686 {
687   HANDLE tcpFile;
688   NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA );
689   IO_STATUS_BLOCK Iosb;
690 
691   TRACE("Called.\n");
692 
693   if( !NT_SUCCESS(status) ) return status;
694 
695   status = NtDeviceIoControlFile( tcpFile,
696                                   NULL,
697                                   NULL,
698                                   NULL,
699                                   &Iosb,
700                                   IOCTL_DELETE_IP_ADDRESS,
701                                   &NteContext,
702                                   sizeof(USHORT),
703                                   NULL,
704                                   0 );
705 
706   closeTcpFile( tcpFile );
707 
708   if (!NT_SUCCESS(status)) {
709       ERR("deleteIpAddress(%lu) returning 0x%lx\n", NteContext, status);
710   }
711 
712   return status;
713 }
714