1 /* Copyright (C) 2003 Art Yerkes
2 * A reimplementation of ifenum.c by Juan Lang
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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.
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.
36 * - We don't support IPv6 addresses here yet -- I moved the upper edge
37 * functions into iphlpv6.c (arty)
39 #include "iphlpapi_private.h"
47 const PWCHAR TcpFileName
= L
"\\Device\\Tcp";
51 /* I'm a bit skittish about maintaining this info in memory, as I'd rather
52 * not add any mutex or critical section blockers to these functions. I've
53 * encountered far too many windows functions that contribute to deadlock
54 * by not announcing themselves. */
55 void interfaceMapInit(void)
57 /* For now, nothing */
60 void interfaceMapFree(void)
65 NTSTATUS
openTcpFile(PHANDLE tcpFile
) {
66 UNICODE_STRING fileName
;
67 OBJECT_ATTRIBUTES objectAttributes
;
68 IO_STATUS_BLOCK ioStatusBlock
;
73 /* Shamelessly ripped from CreateFileW */
74 RtlInitUnicodeString( &fileName
, TcpFileName
);
76 InitializeObjectAttributes( &objectAttributes
,
82 status
= ZwCreateFile( tcpFile
,
83 SYNCHRONIZE
| GENERIC_EXECUTE
|
84 GENERIC_READ
| GENERIC_WRITE
,
88 FILE_ATTRIBUTE_NORMAL
,
89 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
91 FILE_SYNCHRONOUS_IO_NONALERT
,
95 /* String does not need to be freed: it points to the constant
96 * string we provided */
98 TRACE("returning %08x\n", (int)status
);
103 void closeTcpFile( HANDLE h
) {
108 /* A generic thing-getting function which interacts in the right way with
109 * TDI. This may seem oblique, but I'm using it to reduce code and hopefully
110 * make this thing easier to debug.
112 * The things returned can be any of:
120 NTSTATUS
tdiGetSetOfThings( HANDLE tcpFile
,
128 PDWORD numEntries
) {
129 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
131 NTSTATUS status
= STATUS_SUCCESS
;
132 DWORD allocationSizeForEntityArray
= entrySize
* MAX_TDI_ENTITIES
,
133 arraySize
= entrySize
* MAX_TDI_ENTITIES
;
135 TRACE("TdiGetSetOfThings(tcpFile %x,toiClass %x,toiType %x,toiId %x,"
136 "teiEntity %x,fixedPart %d,entrySize %d)\n",
145 req
.ID
.toi_class
= toiClass
;
146 req
.ID
.toi_type
= toiType
;
147 req
.ID
.toi_id
= toiId
;
148 req
.ID
.toi_entity
.tei_entity
= teiEntity
;
150 /* There's a subtle problem here...
151 * If an interface is added at this exact instant, (as if by a PCMCIA
152 * card insertion), the array will still not have enough entries after
153 * have allocated it after the first DeviceIoControl call.
155 * We'll get around this by repeating until the number of interfaces
159 assert( !entitySet
); /* We must not have an entity set allocated */
160 status
= DeviceIoControl( tcpFile
,
161 IOCTL_TCP_QUERY_INFORMATION_EX
,
166 &allocationSizeForEntityArray
,
171 DPRINT("IOCTL Failed\n");
172 return STATUS_UNSUCCESSFUL
;
175 arraySize
= allocationSizeForEntityArray
;
176 entitySet
= HeapAlloc( GetProcessHeap(), 0, arraySize
);
179 status
= STATUS_INSUFFICIENT_RESOURCES
;
180 DPRINT("TdiGetSetOfThings() => %08x\n", (int)status
);
184 status
= DeviceIoControl( tcpFile
,
185 IOCTL_TCP_QUERY_INFORMATION_EX
,
190 &allocationSizeForEntityArray
,
193 /* This is why we have the loop -- we might have added an adapter */
194 if( arraySize
== allocationSizeForEntityArray
)
197 HeapFree( GetProcessHeap(), 0, entitySet
);
202 DPRINT("IOCTL Failed\n");
203 return STATUS_UNSUCCESSFUL
;
206 DPRINT("TdiGetSetOfThings(): Array changed size: %d -> %d.\n",
207 arraySize
, allocationSizeForEntityArray
);
208 } while( TRUE
); /* We break if the array we received was the size we
209 * expected. Therefore, we got here because it wasn't */
211 *numEntries
= (arraySize
- fixedPart
) / entrySize
;
212 *tdiEntitySet
= entitySet
;
214 DPRINT("TdiGetSetOfThings() => Success: %d things @ %08x\n",
215 (int)*numEntries
, (int)entitySet
);
217 return STATUS_SUCCESS
;
220 VOID
tdiFreeThingSet( PVOID things
) {
221 HeapFree( GetProcessHeap(), 0, things
);
224 NTSTATUS tdiGetMibForIfEntity
225 ( HANDLE tcpFile
, TDIEntityID
*ent
, IFEntrySafelySized
*entry
) {
226 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
227 NTSTATUS status
= STATUS_SUCCESS
;
230 DPRINT("TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n",
231 (int)tcpFile
, (int)ent
->tei_instance
);
233 req
.ID
.toi_class
= INFO_CLASS_PROTOCOL
;
234 req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
235 req
.ID
.toi_id
= IF_MIB_STATS_ID
;
236 req
.ID
.toi_entity
= *ent
;
238 status
= DeviceIoControl( tcpFile
,
239 IOCTL_TCP_QUERY_INFORMATION_EX
,
249 DPRINT("IOCTL Failed\n");
250 return STATUS_UNSUCCESSFUL
;
253 DPRINT("TdiGetMibForIfEntity() => {\n"
254 " if_index ....................... %x\n"
255 " if_type ........................ %x\n"
256 " if_mtu ......................... %d\n"
257 " if_speed ....................... %x\n"
258 " if_physaddrlen ................. %d\n",
263 entry
->ent
.if_physaddrlen
);
264 DPRINT(" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n",
265 " if_descr ....................... %s\n",
266 entry
->ent
.if_physaddr
[0] & 0xff,
267 entry
->ent
.if_physaddr
[1] & 0xff,
268 entry
->ent
.if_physaddr
[2] & 0xff,
269 entry
->ent
.if_physaddr
[3] & 0xff,
270 entry
->ent
.if_physaddr
[4] & 0xff,
271 entry
->ent
.if_physaddr
[5] & 0xff,
272 entry
->ent
.if_descr
);
273 DPRINT("} status %08x\n",status
);
278 NTSTATUS
tdiGetEntityIDSet( HANDLE tcpFile
,
279 TDIEntityID
**entitySet
,
280 PDWORD numEntities
) {
281 NTSTATUS status
= tdiGetSetOfThings( tcpFile
,
290 if( NT_SUCCESS(status
) ) {
293 for( i
= 0; i
< *numEntities
; i
++ ) {
294 DPRINT("%-4d: %04x:%08x\n",
296 (*entitySet
)[i
].tei_entity
,
297 (*entitySet
)[i
].tei_instance
);
304 static BOOL
isInterface( TDIEntityID
*if_maybe
) {
306 if_maybe
->tei_entity
== IF_ENTITY
;
309 static BOOL
isLoopback( HANDLE tcpFile
, TDIEntityID
*loop_maybe
) {
310 IFEntrySafelySized entryInfo
;
313 status
= tdiGetMibForIfEntity( tcpFile
,
317 return NT_SUCCESS(status
) && (!entryInfo
.ent
.if_type
||
318 entryInfo
.ent
.if_type
== IFENT_SOFTWARE_LOOPBACK
);
321 NTSTATUS
tdiGetEntityType( HANDLE tcpFile
, TDIEntityID
*ent
, PULONG type
) {
322 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
323 NTSTATUS status
= STATUS_SUCCESS
;
326 DPRINT("TdiGetEntityType(tcpFile %x,entityId %x)\n",
327 (DWORD
)tcpFile
, ent
->tei_instance
);
329 req
.ID
.toi_class
= INFO_CLASS_GENERIC
;
330 req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
331 req
.ID
.toi_id
= ENTITY_TYPE_ID
;
332 req
.ID
.toi_entity
.tei_entity
= ent
->tei_entity
;
333 req
.ID
.toi_entity
.tei_instance
= ent
->tei_instance
;
335 status
= DeviceIoControl( tcpFile
,
336 IOCTL_TCP_QUERY_INFORMATION_EX
,
344 DPRINT("TdiGetEntityType() => %08x %08x\n", *type
, status
);
346 return (status
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
349 static NTSTATUS
getInterfaceInfoSet( HANDLE tcpFile
,
351 PDWORD numInterfaces
) {
353 TDIEntityID
*entIDSet
= 0;
354 NTSTATUS status
= tdiGetEntityIDSet( tcpFile
, &entIDSet
, &numEntities
);
355 IFInfo
*infoSetInt
= 0;
356 BOOL interfaceInfoComplete
;
357 int curInterf
= 0, i
;
359 if( NT_SUCCESS(status
) )
360 infoSetInt
= HeapAlloc( GetProcessHeap(), 0,
361 sizeof(IFInfo
) * numEntities
);
364 for( i
= 0; i
< numEntities
; i
++ ) {
365 if( isInterface( &entIDSet
[i
] ) ) {
366 status
= tdiGetMibForIfEntity
369 &infoSetInt
[curInterf
].if_info
);
370 DPRINT("tdiGetMibForIfEntity: %08x\n", status
);
371 if( NT_SUCCESS(status
) ) {
377 interfaceInfoComplete
= FALSE
;
378 status
= getNthIpEntity( tcpFile
, 0, &ip_ent
);
379 if( NT_SUCCESS(status
) )
380 status
= tdiGetIpAddrsForIpEntity
381 ( tcpFile
, &ip_ent
, &addrs
, &numAddrs
);
382 for( j
= 0; j
< numAddrs
&& NT_SUCCESS(status
); j
++ ) {
383 DPRINT("ADDR %d: index %d (target %d)\n", j
, addrs
[j
].iae_index
, infoSetInt
[curInterf
].if_info
.ent
.if_index
);
384 if( addrs
[j
].iae_index
==
385 infoSetInt
[curInterf
].if_info
.ent
.if_index
) {
386 memcpy( &infoSetInt
[curInterf
].ip_addr
,
388 sizeof( addrs
[j
] ) );
397 if (NT_SUCCESS(status
)) {
398 *infoSet
= infoSetInt
;
399 *numInterfaces
= curInterf
;
401 HeapFree(GetProcessHeap(), 0, infoSetInt
);
406 return STATUS_INSUFFICIENT_RESOURCES
;
410 static DWORD
getNumInterfacesInt(BOOL onlyNonLoopback
)
412 DWORD numEntities
, numInterfaces
= 0;
413 TDIEntityID
*entitySet
;
418 status
= openTcpFile( &tcpFile
);
420 if( !NT_SUCCESS(status
) ) {
421 DPRINT("getNumInterfaces: failed %08x\n", status
);
425 status
= tdiGetEntityIDSet( tcpFile
, &entitySet
, &numEntities
);
427 if( !NT_SUCCESS(status
) ) {
428 DPRINT("getNumInterfaces: failed %08x\n", status
);
432 for( i
= 0; i
< numEntities
; i
++ ) {
433 if( isInterface( &entitySet
[i
] ) &&
435 (onlyNonLoopback
&& !isLoopback( tcpFile
, &entitySet
[i
] ))) )
439 DPRINT("getNumInterfaces: success: %d %d %08x\n",
440 onlyNonLoopback
, numInterfaces
, status
);
442 closeTcpFile( tcpFile
);
444 tdiFreeThingSet( entitySet
);
446 return numInterfaces
;
449 DWORD
getNumInterfaces(void)
451 return getNumInterfacesInt( FALSE
);
454 DWORD
getNumNonLoopbackInterfaces(void)
456 return getNumInterfacesInt( TRUE
);
459 DWORD
getNthInterfaceEntity( HANDLE tcpFile
, DWORD index
, TDIEntityID
*ent
) {
460 DWORD numEntities
= 0;
461 DWORD numInterfaces
= 0;
462 TDIEntityID
*entitySet
= 0;
463 NTSTATUS status
= tdiGetEntityIDSet( tcpFile
, &entitySet
, &numEntities
);
466 if( !NT_SUCCESS(status
) )
469 for( i
= 0; i
< numEntities
; i
++ ) {
470 if( isInterface( &entitySet
[i
] ) ) {
471 if( numInterfaces
== index
) break;
472 else numInterfaces
++;
476 DPRINT("Index %d is entity #%d - %04x:%08x\n", index
, i
,
477 entitySet
[i
].tei_entity
, entitySet
[i
].tei_instance
);
479 if( numInterfaces
== index
&& i
< numEntities
) {
480 memcpy( ent
, &entitySet
[i
], sizeof(*ent
) );
481 tdiFreeThingSet( entitySet
);
482 return STATUS_SUCCESS
;
484 tdiFreeThingSet( entitySet
);
485 return STATUS_UNSUCCESSFUL
;
489 NTSTATUS
getInterfaceInfoByIndex( HANDLE tcpFile
, DWORD index
, IFInfo
*info
) {
492 NTSTATUS status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
495 if( NT_SUCCESS(status
) )
496 for( i
= 0; i
< numInterfaces
; i
++ ) {
497 if( ifInfo
[i
].if_info
.ent
.if_index
== index
) {
498 memcpy( info
, &ifInfo
[i
], sizeof(*info
) );
503 if( NT_SUCCESS(status
) )
504 return i
< numInterfaces
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
509 NTSTATUS
getInterfaceInfoByName( HANDLE tcpFile
, char *name
, IFInfo
*info
) {
513 NTSTATUS status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
515 if( NT_SUCCESS(status
) )
516 for( i
= 0; i
< numInterfaces
; i
++ ) {
517 if( !strcmp(ifInfo
[i
].if_info
.ent
.if_descr
, name
) ) {
518 memcpy( info
, &ifInfo
[i
], sizeof(*info
) );
523 if( NT_SUCCESS(status
) )
524 return i
< numInterfaces
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
529 /* Note that the result of this operation must be freed later */
531 const char *getInterfaceNameByIndex(DWORD index
)
535 char *interfaceName
= 0, *adapter_name
= 0;
536 NTSTATUS status
= openTcpFile( &tcpFile
);
538 if( NT_SUCCESS(status
) ) {
539 status
= getInterfaceInfoByIndex( tcpFile
, index
, &ifInfo
);
541 if( NT_SUCCESS(status
) ) {
542 adapter_name
= ifInfo
.if_info
.ent
.if_descr
;
544 interfaceName
= HeapAlloc( GetProcessHeap(), 0,
545 strlen(adapter_name
) + 1 );
546 strcpy( interfaceName
, adapter_name
);
548 closeTcpFile( tcpFile
);
552 return interfaceName
;
555 void consumeInterfaceName(const char *name
) {
556 HeapFree( GetProcessHeap(), 0, (char *)name
);
559 DWORD
getInterfaceIndexByName(const char *name
, PDWORD index
)
563 NTSTATUS status
= openTcpFile( &tcpFile
);
565 if( NT_SUCCESS(status
) ) {
566 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &ifInfo
);
568 if( NT_SUCCESS(status
) ) {
569 *index
= ifInfo
.if_info
.ent
.if_index
;
570 closeTcpFile( tcpFile
);
577 InterfaceIndexTable
*getInterfaceIndexTableInt( BOOL nonLoopbackOnly
) {
578 DWORD numInterfaces
, curInterface
= 0;
581 InterfaceIndexTable
*ret
= 0;
583 NTSTATUS status
= openTcpFile( &tcpFile
);
585 if( NT_SUCCESS(status
) ) {
586 status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
588 DPRINT("InterfaceInfoSet: %08x, %04x:%08x\n",
590 ifInfo
->entity_id
.tei_entity
,
591 ifInfo
->entity_id
.tei_instance
);
593 if( NT_SUCCESS(status
) ) {
594 ret
= (InterfaceIndexTable
*)
596 sizeof(InterfaceIndexTable
) +
597 (numInterfaces
- 1) * sizeof(DWORD
));
600 ret
->numAllocated
= numInterfaces
;
601 DPRINT("NumInterfaces = %d\n", numInterfaces
);
603 for( i
= 0; i
< numInterfaces
; i
++ ) {
604 DPRINT("Examining interface %d\n", i
);
605 if( !nonLoopbackOnly
||
606 !isLoopback( tcpFile
, &ifInfo
[i
].entity_id
) ) {
607 DPRINT("Interface %d matches (%d)\n", i
, curInterface
);
608 ret
->indexes
[curInterface
++] =
609 ifInfo
[i
].if_info
.ent
.if_index
;
613 ret
->numIndexes
= curInterface
;
616 tdiFreeThingSet( ifInfo
);
618 closeTcpFile( tcpFile
);
624 InterfaceIndexTable
*getInterfaceIndexTable(void) {
625 return getInterfaceIndexTableInt( FALSE
);
628 InterfaceIndexTable
*getNonLoopbackInterfaceIndexTable(void) {
629 return getInterfaceIndexTableInt( TRUE
);
632 DWORD
getInterfaceIPAddrByName(const char *name
)
637 NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile
,
643 getInterfaceInfoByName( tcpFile
, name
, ifInfo
) :
644 getInterfaceInfoByIndex( tcpFile
, index
, ifInfo
);
648 DWORD
getAddrByIndexOrName( char *name
, DWORD index
, IPHLPAddrType addrType
) {
650 HANDLE tcpFile
= INVALID_HANDLE_VALUE
;
651 NTSTATUS status
= STATUS_SUCCESS
;
652 DWORD addrOut
= INADDR_ANY
;
654 status
= openTcpFile( &tcpFile
);
656 if( NT_SUCCESS(status
) ) {
657 status
= getIPAddrEntryForIf( tcpFile
, name
, index
, &ifInfo
);
658 if( NT_SUCCESS(status
) ) {
660 case IPAAddr
: addrOut
= ifInfo
.ip_addr
.iae_addr
; break;
661 case IPABcast
: addrOut
= ifInfo
.ip_addr
.iae_bcastaddr
; break;
662 case IPAMask
: addrOut
= ifInfo
.ip_addr
.iae_mask
; break;
663 case IFMtu
: addrOut
= ifInfo
.if_info
.ent
.if_mtu
; break;
664 case IFStatus
: addrOut
= ifInfo
.if_info
.ent
.if_operstatus
; break;
667 closeTcpFile( &tcpFile
);
673 DWORD
getInterfaceIPAddrByIndex(DWORD index
) {
674 return getAddrByIndexOrName( 0, index
, IPAAddr
);
677 DWORD
getInterfaceBCastAddrByName(const char *name
) {
678 return getAddrByIndexOrName( (char *)name
, 0, IPABcast
);
681 DWORD
getInterfaceBCastAddrByIndex(DWORD index
) {
682 return getAddrByIndexOrName( 0, index
, IPABcast
);
685 DWORD
getInterfaceMaskByName(const char *name
) {
686 return getAddrByIndexOrName( (char *)name
, 0, IPAMask
);
689 DWORD
getInterfaceMaskByIndex(DWORD index
) {
690 return getAddrByIndexOrName( 0, index
, IPAMask
);
693 void getInterfacePhysicalFromInfo( IFInfo
*info
,
694 PDWORD len
, PBYTE addr
, PDWORD type
) {
695 *len
= info
->if_info
.ent
.if_physaddrlen
;
696 memcpy( addr
, info
->if_info
.ent
.if_physaddr
, *len
);
697 *type
= info
->if_info
.ent
.if_type
;
700 DWORD
getInterfacePhysicalByName(const char *name
, PDWORD len
, PBYTE addr
,
705 NTSTATUS status
= openTcpFile( &tcpFile
);
707 if( NT_SUCCESS(status
) ) {
708 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &info
);
709 if( NT_SUCCESS(status
) )
710 getInterfacePhysicalFromInfo( &info
, len
, addr
, type
);
711 closeTcpFile( tcpFile
);
717 DWORD
getInterfacePhysicalByIndex(DWORD index
, PDWORD len
, PBYTE addr
,
722 NTSTATUS status
= openTcpFile( &tcpFile
);
724 if( NT_SUCCESS(status
) ) {
725 status
= getInterfaceInfoByIndex( tcpFile
, index
, &info
);
726 if( NT_SUCCESS(status
) )
727 getInterfacePhysicalFromInfo( &info
, len
, addr
, type
);
728 closeTcpFile( tcpFile
);
734 DWORD
getInterfaceMtuByName(const char *name
, PDWORD mtu
) {
735 *mtu
= getAddrByIndexOrName( (char *)name
, 0, IFMtu
);
736 return STATUS_SUCCESS
;
739 DWORD
getInterfaceMtuByIndex(DWORD index
, PDWORD mtu
) {
740 *mtu
= getAddrByIndexOrName( 0, index
, IFMtu
);
741 return STATUS_SUCCESS
;
744 DWORD
getInterfaceStatusByName(const char *name
, PDWORD status
) {
745 *status
= getAddrByIndexOrName( (char *)name
, 0, IFStatus
);
746 return STATUS_SUCCESS
;
749 DWORD
getInterfaceStatusByIndex(DWORD index
, PDWORD status
)
751 *status
= getAddrByIndexOrName( 0, index
, IFStatus
);
752 return STATUS_SUCCESS
;
755 DWORD
getInterfaceEntryByName(const char *name
, PMIB_IFROW entry
)
759 NTSTATUS status
= openTcpFile( &tcpFile
);
763 if( NT_SUCCESS(status
) ) {
764 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &info
);
766 if( NT_SUCCESS(status
) ) {
767 memcpy( &entry
->wszName
[MAX_INTERFACE_NAME_LEN
],
769 sizeof(info
.if_info
) );
772 DPRINT1("entry->bDescr = %s\n", entry
->bDescr
);
774 closeTcpFile( tcpFile
);
780 DWORD
getInterfaceEntryByIndex(DWORD index
, PMIB_IFROW entry
)
784 NTSTATUS status
= openTcpFile( &tcpFile
);
788 if( NT_SUCCESS(status
) ) {
789 status
= getInterfaceInfoByIndex( tcpFile
, index
, &info
);
791 if( NT_SUCCESS(status
) ) {
792 memcpy( &entry
->wszName
[MAX_INTERFACE_NAME_LEN
],
794 sizeof(info
.if_info
) );
797 closeTcpFile( tcpFile
);
803 char *toIPAddressString(unsigned int addr
, char string
[16])
806 struct in_addr iAddr
;
809 /* extra-anal, just to make auditors happy */
810 strncpy(string
, inet_ntoa(iAddr
), 16);
816 NTSTATUS
addIPAddress( IPAddr Address
, IPMask Mask
, DWORD IfIndex
,
817 PULONG NteContext
, PULONG NteInstance
)
820 NTSTATUS status
= openTcpFile( &tcpFile
);
822 IO_STATUS_BLOCK Iosb
;
826 if( !NT_SUCCESS(status
) ) return status
;
828 Data
.NteContext
= IfIndex
;
829 Data
.NewAddress
= Address
;
830 Data
.NewNetmask
= Mask
;
832 status
= NtDeviceIoControlFile( tcpFile
,
837 IOCTL_SET_IP_ADDRESS
,
843 closeTcpFile( tcpFile
);
845 if( NT_SUCCESS(status
) ) {
846 *NteContext
= Iosb
.Information
;
847 *NteInstance
= Data
.NewAddress
;
851 case STATUS_SUCCESS
: return ERROR_SUCCESS
;
852 case STATUS_DEVICE_DOES_NOT_EXIST
: return ERROR_DEV_NOT_EXIST
;
853 default: return status
;
857 NTSTATUS
deleteIpAddress( ULONG NteContext
)
860 NTSTATUS status
= openTcpFile( &tcpFile
);
861 IO_STATUS_BLOCK Iosb
;
865 if( !NT_SUCCESS(status
) ) return status
;
867 status
= NtDeviceIoControlFile( tcpFile
,
872 IOCTL_DELETE_IP_ADDRESS
,
878 closeTcpFile( tcpFile
);
880 if( NT_SUCCESS(status
) ) return ERROR_SUCCESS
;
881 else return ERROR_GEN_FAILURE
;