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)
40 #include "iphlpapi_private.h"
44 const PWCHAR TcpFileName
= L
"\\Device\\Tcp";
48 /* I'm a bit skittish about maintaining this info in memory, as I'd rather
49 * not add any mutex or critical section blockers to these functions. I've
50 * encountered far too many windows functions that contribute to deadlock
51 * by not announcing themselves. */
52 void interfaceMapInit(void)
54 /* For now, nothing */
57 void interfaceMapFree(void)
62 NTSTATUS
openTcpFile(PHANDLE tcpFile
) {
63 UNICODE_STRING fileName
;
64 OBJECT_ATTRIBUTES objectAttributes
;
65 IO_STATUS_BLOCK ioStatusBlock
;
70 /* Shamelessly ripped from CreateFileW */
71 RtlInitUnicodeString( &fileName
, TcpFileName
);
73 InitializeObjectAttributes( &objectAttributes
,
79 status
= ZwCreateFile( tcpFile
,
80 SYNCHRONIZE
| GENERIC_EXECUTE
,
84 FILE_ATTRIBUTE_NORMAL
,
85 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
87 FILE_SYNCHRONOUS_IO_NONALERT
,
91 /* String does not need to be freed: it points to the constant
92 * string we provided */
94 TRACE("returning %08x\n", (int)status
);
99 void closeTcpFile( HANDLE h
) {
104 /* A generic thing-getting function which interacts in the right way with
105 * TDI. This may seem oblique, but I'm using it to reduce code and hopefully
106 * make this thing easier to debug.
108 * The things returned can be any of:
116 NTSTATUS
tdiGetSetOfThings( HANDLE tcpFile
,
124 PDWORD numEntries
) {
125 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
127 NTSTATUS status
= STATUS_SUCCESS
;
128 DWORD allocationSizeForEntityArray
= entrySize
* MAX_TDI_ENTITIES
,
129 arraySize
= entrySize
* MAX_TDI_ENTITIES
;
131 DPRINT("TdiGetSetOfThings(tcpFile %x,toiClass %x,toiType %x,toiId %x,"
132 "teiEntity %x,fixedPart %d,entrySize %d)\n",
141 req
.ID
.toi_class
= toiClass
;
142 req
.ID
.toi_type
= toiType
;
143 req
.ID
.toi_id
= toiId
;
144 req
.ID
.toi_entity
.tei_entity
= teiEntity
;
146 /* There's a subtle problem here...
147 * If an interface is added at this exact instant, (as if by a PCMCIA
148 * card insertion), the array will still not have enough entries after
149 * have allocated it after the first DeviceIoControl call.
151 * We'll get around this by repeating until the number of interfaces
155 ASSERT( !entitySet
); /* We must not have an entity set allocated */
156 status
= DeviceIoControl( tcpFile
,
157 IOCTL_TCP_QUERY_INFORMATION_EX
,
162 &allocationSizeForEntityArray
,
165 if( !NT_SUCCESS(status
) ) {
166 DPRINT("TdiGetSetOfThings() => %08x\n", (int)status
);
170 arraySize
= allocationSizeForEntityArray
;
171 entitySet
= HeapAlloc( GetProcessHeap(), 0, arraySize
);
174 status
= STATUS_INSUFFICIENT_RESOURCES
;
175 DPRINT("TdiGetSetOfThings() => %08x\n", (int)status
);
179 status
= DeviceIoControl( tcpFile
,
180 IOCTL_TCP_QUERY_INFORMATION_EX
,
185 &allocationSizeForEntityArray
,
188 /* This is why we have the loop -- we might have added an adapter */
189 if( arraySize
== allocationSizeForEntityArray
)
192 HeapFree( GetProcessHeap(), 0, entitySet
);
195 if( !NT_SUCCESS(status
) ) {
196 DPRINT("TdiGetSetOfThings() => %08x\n", (int)status
);
200 DPRINT("TdiGetSetOfThings(): Array changed size: %d -> %d.\n",
201 arraySize
, allocationSizeForEntityArray
);
202 } while( TRUE
); /* We break if the array we received was the size we
203 * expected. Therefore, we got here because it wasn't */
205 *numEntries
= (arraySize
- fixedPart
) / entrySize
;
206 *tdiEntitySet
= entitySet
;
208 DPRINT("TdiGetSetOfThings() => Success: %d things @ %08x\n",
209 (int)*numEntries
, (int)entitySet
);
211 return STATUS_SUCCESS
;
214 VOID
tdiFreeThingSet( PVOID things
) {
215 HeapFree( GetProcessHeap(), 0, things
);
218 NTSTATUS tdiGetMibForIfEntity
219 ( HANDLE tcpFile
, TDIEntityID
*ent
, IFEntrySafelySized
*entry
) {
220 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
221 NTSTATUS status
= STATUS_SUCCESS
;
224 DPRINT("TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n",
225 (int)tcpFile
, (int)ent
->tei_instance
);
227 req
.ID
.toi_class
= INFO_CLASS_PROTOCOL
;
228 req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
229 req
.ID
.toi_id
= IF_MIB_STATS_ID
;
230 req
.ID
.toi_entity
= *ent
;
232 status
= DeviceIoControl( tcpFile
,
233 IOCTL_TCP_QUERY_INFORMATION_EX
,
241 if( !NT_SUCCESS(status
) ) {
242 TRACE("failure: %08x\n", status
);
244 } else TRACE("Success.\n");
246 DPRINT("TdiGetMibForIfEntity() => {\n"
247 " if_index ....................... %x\n"
248 " if_type ........................ %x\n"
249 " if_mtu ......................... %d\n"
250 " if_speed ....................... %x\n"
251 " if_physaddrlen ................. %d\n",
256 entry
->ent
.if_physaddrlen
);
257 DPRINT(" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n",
258 " if_descr ....................... %s\n",
259 entry
->ent
.if_physaddr
[0] & 0xff,
260 entry
->ent
.if_physaddr
[1] & 0xff,
261 entry
->ent
.if_physaddr
[2] & 0xff,
262 entry
->ent
.if_physaddr
[3] & 0xff,
263 entry
->ent
.if_physaddr
[4] & 0xff,
264 entry
->ent
.if_physaddr
[5] & 0xff,
265 entry
->ent
.if_descr
);
266 DPRINT("} status %08x\n",status
);
271 NTSTATUS
tdiGetEntityIDSet( HANDLE tcpFile
,
272 TDIEntityID
**entitySet
,
273 PDWORD numEntities
) {
274 NTSTATUS status
= tdiGetSetOfThings( tcpFile
,
283 if( NT_SUCCESS(status
) ) {
286 for( i
= 0; i
< *numEntities
; i
++ ) {
287 DPRINT("%-4d: %04x:%08x\n",
289 (*entitySet
)[i
].tei_entity
,
290 (*entitySet
)[i
].tei_instance
);
297 static BOOL
isInterface( TDIEntityID
*if_maybe
) {
299 if_maybe
->tei_entity
== IF_ENTITY
;
302 static BOOL
isLoopback( HANDLE tcpFile
, TDIEntityID
*loop_maybe
) {
303 IFEntrySafelySized entryInfo
;
305 tdiGetMibForIfEntity( tcpFile
,
309 return !entryInfo
.ent
.if_type
||
310 entryInfo
.ent
.if_type
== IFENT_SOFTWARE_LOOPBACK
;
313 NTSTATUS
tdiGetEntityType( HANDLE tcpFile
, TDIEntityID
*ent
, PULONG type
) {
314 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
315 NTSTATUS status
= STATUS_SUCCESS
;
318 DPRINT("TdiGetEntityType(tcpFile %x,entityId %x)\n",
319 (DWORD
)tcpFile
, ent
->tei_instance
);
321 req
.ID
.toi_class
= INFO_CLASS_GENERIC
;
322 req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
323 req
.ID
.toi_id
= ENTITY_TYPE_ID
;
324 req
.ID
.toi_entity
.tei_entity
= ent
->tei_entity
;
325 req
.ID
.toi_entity
.tei_instance
= ent
->tei_instance
;
327 status
= DeviceIoControl( tcpFile
,
328 IOCTL_TCP_QUERY_INFORMATION_EX
,
336 DPRINT("TdiGetEntityType() => %08x %08x\n", *type
, status
);
341 static NTSTATUS
getInterfaceInfoSet( HANDLE tcpFile
,
343 PDWORD numInterfaces
) {
345 TDIEntityID
*entIDSet
= 0;
346 NTSTATUS status
= tdiGetEntityIDSet( tcpFile
, &entIDSet
, &numEntities
);
347 IFInfo
*infoSetInt
= 0;
348 BOOL interfaceInfoComplete
;
349 int curInterf
= 0, i
;
351 if( NT_SUCCESS(status
) )
352 infoSetInt
= HeapAlloc( GetProcessHeap(), 0,
353 sizeof(IFInfo
) * numEntities
);
356 for( i
= 0; i
< numEntities
; i
++ ) {
357 if( isInterface( &entIDSet
[i
] ) ) {
358 status
= tdiGetMibForIfEntity
361 &infoSetInt
[curInterf
].if_info
);
362 DPRINT("tdiGetMibForIfEntity: %08x\n", status
);
363 if( NT_SUCCESS(status
) ) {
369 interfaceInfoComplete
= FALSE
;
370 status
= getNthIpEntity( tcpFile
, 0, &ip_ent
);
371 if( NT_SUCCESS(status
) )
372 status
= tdiGetIpAddrsForIpEntity
373 ( tcpFile
, &ip_ent
, &addrs
, &numAddrs
);
374 for( k
= 0; k
< numAddrs
&& NT_SUCCESS(status
); k
++ ) {
375 DPRINT("ADDR %d: index %d (target %d)\n", k
, addrs
[k
].iae_index
, infoSetInt
[curInterf
].if_info
.ent
.if_index
);
376 if( addrs
[k
].iae_index
==
377 infoSetInt
[curInterf
].if_info
.ent
.if_index
) {
378 memcpy( &infoSetInt
[curInterf
].ip_addr
,
380 sizeof( addrs
[k
] ) );
390 *infoSet
= infoSetInt
;
391 *numInterfaces
= curInterf
;
393 return STATUS_SUCCESS
;
396 static DWORD
getNumInterfacesInt(BOOL onlyNonLoopback
)
398 DWORD numEntities
, numInterfaces
= 0;
399 TDIEntityID
*entitySet
;
404 status
= openTcpFile( &tcpFile
);
406 if( !NT_SUCCESS(status
) ) {
407 DPRINT("getNumInterfaces: failed %08x\n", status
);
411 status
= tdiGetEntityIDSet( tcpFile
, &entitySet
, &numEntities
);
413 if( !NT_SUCCESS(status
) ) {
414 DPRINT("getNumInterfaces: failed %08x\n", status
);
418 closeTcpFile( tcpFile
);
420 for( i
= 0; i
< numEntities
; i
++ ) {
421 if( isInterface( &entitySet
[i
] ) &&
423 (onlyNonLoopback
&& !isLoopback( tcpFile
, &entitySet
[i
] ))) )
427 DPRINT("getNumInterfaces: success: %d %d %08x\n",
428 onlyLoopback
, numInterfaces
, status
);
430 tdiFreeThingSet( entitySet
);
432 return numInterfaces
;
435 DWORD
getNumInterfaces(void)
437 return getNumInterfacesInt( FALSE
);
440 DWORD
getNumNonLoopbackInterfaces(void)
442 return getNumInterfacesInt( TRUE
);
445 DWORD
getNthInterfaceEntity( HANDLE tcpFile
, DWORD index
, TDIEntityID
*ent
) {
446 DWORD numEntities
= 0;
447 DWORD numInterfaces
= 0;
448 TDIEntityID
*entitySet
= 0;
449 NTSTATUS status
= tdiGetEntityIDSet( tcpFile
, &entitySet
, &numEntities
);
452 if( !NT_SUCCESS(status
) )
455 for( i
= 0; i
< numEntities
; i
++ ) {
456 if( isInterface( &entitySet
[i
] ) ) {
457 if( numInterfaces
== index
) break;
458 else numInterfaces
++;
462 DPRINT("Index %d is entity #%d - %04x:%08x\n", index
, i
,
463 entitySet
[i
].tei_entity
, entitySet
[i
].tei_instance
);
465 if( numInterfaces
== index
&& i
< numEntities
) {
466 memcpy( ent
, &entitySet
[i
], sizeof(*ent
) );
467 tdiFreeThingSet( entitySet
);
468 return STATUS_SUCCESS
;
470 tdiFreeThingSet( entitySet
);
471 return STATUS_UNSUCCESSFUL
;
475 NTSTATUS
getInterfaceInfoByIndex( HANDLE tcpFile
, DWORD index
, IFInfo
*info
) {
478 NTSTATUS status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
481 if( NT_SUCCESS(status
) )
482 for( i
= 0; i
< numInterfaces
; i
++ ) {
483 if( ifInfo
[i
].if_info
.ent
.if_index
== index
) {
484 memcpy( info
, &ifInfo
[i
], sizeof(*info
) );
489 if( NT_SUCCESS(status
) )
490 return i
< numInterfaces
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
495 NTSTATUS
getInterfaceInfoByName( HANDLE tcpFile
, char *name
, IFInfo
*info
) {
499 NTSTATUS status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
501 if( NT_SUCCESS(status
) )
502 for( i
= 0; i
< numInterfaces
; i
++ ) {
503 if( !strcmp(ifInfo
[i
].if_info
.ent
.if_descr
, name
) ) {
504 memcpy( info
, &ifInfo
[i
], sizeof(*info
) );
509 if( NT_SUCCESS(status
) )
510 return i
< numInterfaces
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
515 /* Note that the result of this operation must be freed later */
517 const char *getInterfaceNameByIndex(DWORD index
)
521 char *interfaceName
= 0, *adapter_name
= 0;
522 NTSTATUS status
= openTcpFile( &tcpFile
);
524 if( NT_SUCCESS(status
) ) {
525 status
= getInterfaceInfoByIndex( tcpFile
, index
, &ifInfo
);
527 if( NT_SUCCESS(status
) ) {
528 adapter_name
= ifInfo
.if_info
.ent
.if_descr
;
530 interfaceName
= HeapAlloc( GetProcessHeap(), 0,
531 strlen(adapter_name
) + 1 );
532 strcpy( interfaceName
, adapter_name
);
534 closeTcpFile( tcpFile
);
538 return interfaceName
;
541 void consumeInterfaceName(const char *name
) {
542 HeapFree( GetProcessHeap(), 0, (char *)name
);
545 DWORD
getInterfaceIndexByName(const char *name
, PDWORD index
)
549 NTSTATUS status
= openTcpFile( &tcpFile
);
551 if( NT_SUCCESS(status
) ) {
552 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &ifInfo
);
554 if( NT_SUCCESS(status
) ) {
555 *index
= ifInfo
.if_info
.ent
.if_index
;
556 closeTcpFile( tcpFile
);
563 InterfaceIndexTable
*getInterfaceIndexTableInt( BOOL nonLoopbackOnly
) {
564 DWORD numInterfaces
, curInterface
= 0;
567 InterfaceIndexTable
*ret
= 0;
569 NTSTATUS status
= openTcpFile( &tcpFile
);
571 if( NT_SUCCESS(status
) ) {
572 status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
574 DPRINT("InterfaceInfoSet: %08x, %04x:%08x\n",
576 ifInfo
->entity_id
.tei_entity
,
577 ifInfo
->entity_id
.tei_instance
);
579 if( NT_SUCCESS(status
) ) {
580 ret
= (InterfaceIndexTable
*)
582 sizeof(InterfaceIndexTable
) +
583 (numInterfaces
- 1) * sizeof(DWORD
));
586 ret
->numAllocated
= numInterfaces
;
587 DPRINT("NumInterfaces = %d\n", numInterfaces
);
589 for( i
= 0; i
< numInterfaces
; i
++ ) {
590 DPRINT("Examining interface %d\n", i
);
591 if( !nonLoopbackOnly
||
592 !isLoopback( tcpFile
, &ifInfo
[i
].entity_id
) ) {
593 DPRINT("Interface %d matches (%d)\n", i
, curInterface
);
594 ret
->indexes
[curInterface
++] =
595 ifInfo
[i
].if_info
.ent
.if_index
;
599 ret
->numIndexes
= curInterface
;
602 tdiFreeThingSet( ifInfo
);
604 closeTcpFile( tcpFile
);
610 InterfaceIndexTable
*getInterfaceIndexTable(void) {
611 return getInterfaceIndexTableInt( FALSE
);
614 InterfaceIndexTable
*getNonLoopbackInterfaceIndexTable(void) {
615 return getInterfaceIndexTableInt( TRUE
);
618 DWORD
getInterfaceIPAddrByName(const char *name
)
623 NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile
,
629 getInterfaceInfoByName( tcpFile
, name
, ifInfo
) :
630 getInterfaceInfoByIndex( tcpFile
, index
, ifInfo
);
634 DWORD
getAddrByIndexOrName( char *name
, DWORD index
, IPHLPAddrType addrType
) {
636 HANDLE tcpFile
= INVALID_HANDLE_VALUE
;
637 NTSTATUS status
= STATUS_SUCCESS
;
638 DWORD addrOut
= INADDR_ANY
;
640 status
= openTcpFile( &tcpFile
);
642 if( NT_SUCCESS(status
) ) {
643 status
= getIPAddrEntryForIf( tcpFile
, name
, index
, &ifInfo
);
644 if( NT_SUCCESS(status
) ) {
646 case IPAAddr
: addrOut
= ifInfo
.ip_addr
.iae_addr
; break;
647 case IPABcast
: addrOut
= ifInfo
.ip_addr
.iae_bcastaddr
; break;
648 case IPAMask
: addrOut
= ifInfo
.ip_addr
.iae_mask
; break;
649 case IFMtu
: addrOut
= ifInfo
.if_info
.ent
.if_mtu
; break;
650 case IFStatus
: addrOut
= ifInfo
.if_info
.ent
.if_operstatus
; break;
653 closeTcpFile( &tcpFile
);
659 DWORD
getInterfaceIPAddrByIndex(DWORD index
) {
660 return getAddrByIndexOrName( 0, index
, IPAAddr
);
663 DWORD
getInterfaceBCastAddrByName(const char *name
) {
664 return getAddrByIndexOrName( (char *)name
, 0, IPABcast
);
667 DWORD
getInterfaceBCastAddrByIndex(DWORD index
) {
668 return getAddrByIndexOrName( 0, index
, IPABcast
);
671 DWORD
getInterfaceMaskByName(const char *name
) {
672 return getAddrByIndexOrName( (char *)name
, 0, IPAMask
);
675 DWORD
getInterfaceMaskByIndex(DWORD index
) {
676 return getAddrByIndexOrName( 0, index
, IPAMask
);
679 void getInterfacePhysicalFromInfo( IFInfo
*info
,
680 PDWORD len
, PBYTE addr
, PDWORD type
) {
681 *len
= info
->if_info
.ent
.if_physaddrlen
;
682 memcpy( addr
, info
->if_info
.ent
.if_physaddr
, *len
);
683 *type
= info
->if_info
.ent
.if_type
;
686 DWORD
getInterfacePhysicalByName(const char *name
, PDWORD len
, PBYTE addr
,
691 NTSTATUS status
= openTcpFile( &tcpFile
);
693 if( NT_SUCCESS(status
) ) {
694 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &info
);
695 if( NT_SUCCESS(status
) )
696 getInterfacePhysicalFromInfo( &info
, len
, addr
, type
);
697 closeTcpFile( tcpFile
);
703 DWORD
getInterfacePhysicalByIndex(DWORD index
, PDWORD len
, PBYTE addr
,
708 NTSTATUS status
= openTcpFile( &tcpFile
);
710 if( NT_SUCCESS(status
) ) {
711 status
= getInterfaceInfoByIndex( tcpFile
, index
, &info
);
712 if( NT_SUCCESS(status
) )
713 getInterfacePhysicalFromInfo( &info
, len
, addr
, type
);
714 closeTcpFile( tcpFile
);
720 DWORD
getInterfaceMtuByName(const char *name
, PDWORD mtu
) {
721 *mtu
= getAddrByIndexOrName( (char *)name
, 0, IFMtu
);
722 return STATUS_SUCCESS
;
725 DWORD
getInterfaceMtuByIndex(DWORD index
, PDWORD mtu
) {
726 *mtu
= getAddrByIndexOrName( 0, index
, IFMtu
);
727 return STATUS_SUCCESS
;
730 DWORD
getInterfaceStatusByName(const char *name
, PDWORD status
) {
731 *status
= getAddrByIndexOrName( (char *)name
, 0, IFStatus
);
732 return STATUS_SUCCESS
;
735 DWORD
getInterfaceStatusByIndex(DWORD index
, PDWORD status
)
737 *status
= getAddrByIndexOrName( 0, index
, IFStatus
);
738 return STATUS_SUCCESS
;
741 DWORD
getInterfaceEntryByName(const char *name
, PMIB_IFROW entry
)
745 NTSTATUS status
= openTcpFile( &tcpFile
);
749 if( NT_SUCCESS(status
) ) {
750 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &info
);
752 if( NT_SUCCESS(status
) ) {
753 memcpy( &entry
->wszName
[MAX_INTERFACE_NAME_LEN
],
755 sizeof(info
.if_info
) );
758 closeTcpFile( tcpFile
);
764 DWORD
getInterfaceEntryByIndex(DWORD index
, PMIB_IFROW entry
)
768 NTSTATUS status
= openTcpFile( &tcpFile
);
772 if( NT_SUCCESS(status
) ) {
773 status
= getInterfaceInfoByIndex( tcpFile
, index
, &info
);
775 if( NT_SUCCESS(status
) ) {
776 memcpy( &entry
->wszName
[MAX_INTERFACE_NAME_LEN
],
778 sizeof(info
.if_info
) );
781 closeTcpFile( tcpFile
);
787 char *toIPAddressString(unsigned int addr
, char string
[16])
790 struct in_addr iAddr
;
793 /* extra-anal, just to make auditors happy */
794 strncpy(string
, inet_ntoa(iAddr
), 16);