const char *getInterfaceNameByIndex(DWORD index) { IFInfo ifInfo; HANDLE tcpFile; char *interfaceName = 0, *adapter_name = 0; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); if( NT_SUCCESS(status) ) { status = getInterfaceInfoByIndex( tcpFile, index, &ifInfo ); if( NT_SUCCESS(status) ) { adapter_name = (char *)ifInfo.if_info.ent.if_descr; interfaceName = HeapAlloc( GetProcessHeap(), 0, strlen(adapter_name) + 1 ); if (!interfaceName) return NULL; strcpy( interfaceName, adapter_name ); } closeTcpFile( tcpFile ); } return interfaceName; }
NTSTATUS deleteIpAddress( ULONG NteContext ) { HANDLE tcpFile; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ); IO_STATUS_BLOCK Iosb; TRACE("Called.\n"); if( !NT_SUCCESS(status) ) return status; status = NtDeviceIoControlFile( tcpFile, NULL, NULL, NULL, &Iosb, IOCTL_DELETE_IP_ADDRESS, &NteContext, sizeof(USHORT), NULL, 0 ); closeTcpFile( tcpFile ); if (!NT_SUCCESS(status)) { ERR("deleteIpAddress(%lu) returning 0x%lx\n", NteContext, status); } return status; }
DWORD deleteIpForwardEntry( PMIB_IPFORWARDROW pRoute ) { HANDLE tcpFile; NTSTATUS status = openTcpFile( &tcpFile ); TCP_REQUEST_SET_INFORMATION_EX_ROUTE_ENTRY req = TCP_REQUEST_SET_INFORMATION_INIT; IPRouteEntry *rte; TDIEntityID id; DWORD returnSize = 0; TRACE("Called.\n"); if( NT_SUCCESS(status) ) { status = getNthIpEntity( tcpFile, pRoute->dwForwardIfIndex, &id ); if( NT_SUCCESS(status) ) { req.Req.ID.toi_class = INFO_CLASS_PROTOCOL; req.Req.ID.toi_type = INFO_TYPE_PROVIDER; req.Req.ID.toi_id = IP_MIB_ARPTABLE_ENTRY_ID; req.Req.ID.toi_entity.tei_instance = id.tei_instance; req.Req.ID.toi_entity.tei_entity = CL_NL_ENTITY; req.Req.BufferSize = sizeof(*rte); rte = (IPRouteEntry *)&req.Req.Buffer[0]; // dwForwardPolicy // dwForwardNextHopAS rte->ire_dest = pRoute->dwForwardDest; rte->ire_mask = INADDR_NONE; rte->ire_gw = pRoute->dwForwardNextHop; rte->ire_index = pRoute->dwForwardIfIndex; rte->ire_type = IP_FORWARD_DEL; rte->ire_proto = pRoute->dwForwardProto; rte->ire_age = pRoute->dwForwardAge; rte->ire_metric1 = pRoute->dwForwardMetric1; rte->ire_metric2 = INADDR_NONE; rte->ire_metric3 = INADDR_NONE; rte->ire_metric4 = INADDR_NONE; rte->ire_metric5 = INADDR_NONE; status = DeviceIoControl( tcpFile, IOCTL_TCP_SET_INFORMATION_EX, &req, sizeof(req), NULL, 0, &returnSize, NULL ); } closeTcpFile( tcpFile ); } TRACE("Returning: %08x (IOCTL was %08x)\n", status, IOCTL_TCP_SET_INFORMATION_EX); if( NT_SUCCESS(status) ) return NO_ERROR; else return status; }
DWORD getNumArpEntries(void) { DWORD numEntities; TDIEntityID *entitySet = NULL; HANDLE tcpFile; int i, totalNumber = 0; NTSTATUS status; PMIB_IPNETROW IpArpTable = NULL; DWORD returnSize; TRACE("called.\n"); status = openTcpFile( &tcpFile ); if( !NT_SUCCESS(status) ) { TRACE("failure: %08x\n", (int)status ); return 0; } status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); for( i = 0; i < numEntities; i++ ) { if( isInterface( &entitySet[i] ) && hasArp( tcpFile, &entitySet[i] ) ) { status = tdiGetSetOfThings( tcpFile, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER, IP_MIB_ARPTABLE_ENTRY_ID, AT_ENTITY, entitySet[i].tei_instance, 0, sizeof(MIB_IPNETROW), (PVOID *)&IpArpTable, &returnSize ); if( status == STATUS_SUCCESS ) totalNumber += returnSize; if( IpArpTable ) { tdiFreeThingSet( IpArpTable ); IpArpTable = NULL; } } } closeTcpFile( tcpFile ); if( IpArpTable ) tdiFreeThingSet( IpArpTable ); if( entitySet ) tdiFreeThingSet( entitySet ); return totalNumber; }
DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr, PDWORD type) { HANDLE tcpFile; IFInfo info; NTSTATUS status = openTcpFile( &tcpFile ); if( NT_SUCCESS(status) ) { status = getInterfaceInfoByName( tcpFile, (char *)name, &info ); if( NT_SUCCESS(status) ) getInterfacePhysicalFromInfo( &info, len, addr, type ); closeTcpFile( tcpFile ); } return status; }
DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr, PDWORD type) { HANDLE tcpFile; IFInfo info; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); if( NT_SUCCESS(status) ) { status = getInterfaceInfoByIndex( tcpFile, index, &info ); if( NT_SUCCESS(status) ) getInterfacePhysicalFromInfo( &info, len, addr, type ); closeTcpFile( tcpFile ); } return status; }
InterfaceIndexTable *getInterfaceIndexTableInt( BOOL nonLoopbackOnly ) { DWORD numInterfaces, curInterface = 0; int i; IFInfo *ifInfo; InterfaceIndexTable *ret = 0; HANDLE tcpFile; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); if( NT_SUCCESS(status) ) { status = getInterfaceInfoSet( tcpFile, &ifInfo, &numInterfaces ); TRACE("InterfaceInfoSet: %08x, %04x:%08x\n", status, ifInfo->entity_id.tei_entity, ifInfo->entity_id.tei_instance); if( NT_SUCCESS(status) ) { ret = (InterfaceIndexTable *) calloc(1, sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD)); if (ret) { ret->numAllocated = numInterfaces; TRACE("NumInterfaces = %d\n", numInterfaces); for( i = 0; i < numInterfaces; i++ ) { TRACE("Examining interface %d\n", i); if( !nonLoopbackOnly || !isLoopback( tcpFile, &ifInfo[i].entity_id ) ) { TRACE("Interface %d matches (%d)\n", i, curInterface); ret->indexes[curInterface++] = ifInfo[i].if_info.ent.if_index; } } ret->numIndexes = curInterface; } tdiFreeThingSet( ifInfo ); } closeTcpFile( tcpFile ); } return ret; }
DWORD getNumRoutes(void) { DWORD numEntities, numRoutes = 0; TDIEntityID *entitySet; HANDLE tcpFile; int i; NTSTATUS status; TRACE("called.\n"); status = openTcpFile( &tcpFile ); if( !NT_SUCCESS(status) ) { TRACE("failure: %08x\n", (int)status ); return 0; } status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); if( !NT_SUCCESS(status) ) { TRACE("failure: %08x\n", (int)status ); closeTcpFile( tcpFile ); return 0; } for( i = 0; i < numEntities; i++ ) { if( isIpEntity( tcpFile, &entitySet[i] ) ) { IPSNMPInfo isnmp; memset( &isnmp, 0, sizeof( isnmp ) ); status = tdiGetMibForIpEntity( tcpFile, &entitySet[i], &isnmp ); if( !NT_SUCCESS(status) ) { tdiFreeThingSet( entitySet ); closeTcpFile( tcpFile ); return status; } numRoutes += isnmp.ipsi_numroutes; } } TRACE("numRoutes: %d\n", (int)numRoutes); closeTcpFile( tcpFile ); return numRoutes; }
DWORD getInterfaceIndexByName(const char *name, PDWORD index) { IFInfo ifInfo; HANDLE tcpFile; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); if( NT_SUCCESS(status) ) { status = getInterfaceInfoByName( tcpFile, (char *)name, &ifInfo ); if( NT_SUCCESS(status) ) { *index = ifInfo.if_info.ent.if_index; } closeTcpFile( tcpFile ); } return status; }
NTSTATUS addIPAddress( IPAddr Address, IPMask Mask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance ) { HANDLE tcpFile; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA | FILE_WRITE_DATA ); IP_SET_DATA Data; IO_STATUS_BLOCK Iosb; TRACE("Called.\n"); if( !NT_SUCCESS(status) ) return status; Data.NteContext = IfIndex; Data.NewAddress = Address; Data.NewNetmask = Mask; status = NtDeviceIoControlFile( tcpFile, NULL, NULL, NULL, &Iosb, IOCTL_SET_IP_ADDRESS, &Data, sizeof(Data), &Data, sizeof(Data) ); closeTcpFile( tcpFile ); if( NT_SUCCESS(status) ) { *NteContext = Iosb.Information; *NteInstance = Data.NewAddress; } if (!NT_SUCCESS(status)) { ERR("addIPAddress for if %d returning 0x%lx\n", IfIndex, status); } return status; }
static DWORD getNumInterfacesInt(BOOL onlyNonLoopback) { DWORD numEntities, numInterfaces = 0; TDIEntityID *entitySet; HANDLE tcpFile; NTSTATUS status; int i; status = openTcpFile( &tcpFile, FILE_READ_DATA ); if( !NT_SUCCESS(status) ) { WARN("getNumInterfaces: failed %08x\n", status ); return 0; } status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); if( !NT_SUCCESS(status) ) { WARN("getNumInterfaces: failed %08x\n", status ); closeTcpFile( tcpFile ); return 0; } for( i = 0; i < numEntities; i++ ) { if( isInterface( &entitySet[i] ) && (!onlyNonLoopback || (onlyNonLoopback && !isLoopback( tcpFile, &entitySet[i] ))) ) numInterfaces++; } TRACE("getNumInterfaces: success: %d %d %08x\n", onlyNonLoopback, numInterfaces, status ); closeTcpFile( tcpFile ); tdiFreeThingSet( entitySet ); return numInterfaces; }
DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry) { HANDLE tcpFile; IFInfo info; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); TRACE("Called.\n"); if( NT_SUCCESS(status) ) { status = getInterfaceInfoByIndex( tcpFile, index, &info ); if( NT_SUCCESS(status) ) { memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN], &info.if_info, sizeof(info.if_info) ); } closeTcpFile( tcpFile ); } return status; }
DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry) { HANDLE tcpFile; IFInfo info; NTSTATUS status = openTcpFile( &tcpFile, FILE_READ_DATA ); TRACE("Called.\n"); if( NT_SUCCESS(status) ) { status = getInterfaceInfoByName( tcpFile, (char *)name, &info ); if( NT_SUCCESS(status) ) { memcpy( &entry->wszName[MAX_INTERFACE_NAME_LEN], &info.if_info, sizeof(info.if_info) ); } TRACE("entry->bDescr = %s\n", entry->bDescr); closeTcpFile( tcpFile ); } return status; }
DWORD getAddrByIndexOrName( char *name, DWORD index, IPHLPAddrType addrType ) { IFInfo ifInfo; HANDLE tcpFile; NTSTATUS status = STATUS_SUCCESS; DWORD addrOut = INADDR_ANY; status = openTcpFile( &tcpFile, FILE_READ_DATA ); if( NT_SUCCESS(status) ) { status = getIPAddrEntryForIf( tcpFile, name, index, &ifInfo ); if( NT_SUCCESS(status) ) { switch( addrType ) { case IPAAddr: addrOut = ifInfo.ip_addr.iae_addr; break; case IPABcast: addrOut = ifInfo.ip_addr.iae_bcastaddr; break; case IPAMask: addrOut = ifInfo.ip_addr.iae_mask; break; case IFMtu: addrOut = ifInfo.if_info.ent.if_mtu; break; case IFStatus: addrOut = ifInfo.if_info.ent.if_operstatus; break; } } closeTcpFile( tcpFile ); } return addrOut; }
PMIB_IPNETTABLE getArpTable(void) { DWORD numEntities, returnSize; TDIEntityID *entitySet; HANDLE tcpFile; int i, totalNumber, TmpIdx, CurrIdx = 0; NTSTATUS status; PMIB_IPNETTABLE IpArpTable = NULL; PMIB_IPNETROW AdapterArpTable = NULL; TRACE("called.\n"); totalNumber = getNumArpEntries(); status = openTcpFile( &tcpFile ); if( !NT_SUCCESS(status) ) { TRACE("failure: %08x\n", (int)status ); return 0; } IpArpTable = HeapAlloc ( GetProcessHeap(), 0, sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber) ); if (!IpArpTable) { closeTcpFile(tcpFile); return NULL; } status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); for( i = 0; i < numEntities; i++ ) { if( isInterface( &entitySet[i] ) && hasArp( tcpFile, &entitySet[i] ) ) { status = tdiGetSetOfThings( tcpFile, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER, IP_MIB_ARPTABLE_ENTRY_ID, AT_ENTITY, entitySet[i].tei_instance, 0, sizeof(MIB_IPNETROW), (PVOID *)&AdapterArpTable, &returnSize ); if( status == STATUS_SUCCESS ) { for( TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++ ) IpArpTable->table[CurrIdx] = AdapterArpTable[TmpIdx]; tdiFreeThingSet( AdapterArpTable ); } } } closeTcpFile( tcpFile ); tdiFreeThingSet( entitySet ); IpArpTable->dwNumEntries = CurrIdx; return IpArpTable; }
RouteTable *getRouteTable(void) { RouteTable *out_route_table; DWORD numRoutes = getNumRoutes(), routesAdded = 0; TDIEntityID ent; HANDLE tcpFile; NTSTATUS status = openTcpFile( &tcpFile ); int i; if( !NT_SUCCESS(status) ) return 0; TRACE("GETTING ROUTE TABLE\n"); out_route_table = HeapAlloc( GetProcessHeap(), 0, sizeof(RouteTable) + (sizeof(RouteEntry) * (numRoutes - 1)) ); if (!out_route_table) { closeTcpFile(tcpFile); return NULL; } out_route_table->numRoutes = numRoutes; for( i = 0; routesAdded < out_route_table->numRoutes; i++ ) { int j; IPRouteEntry *route_set; getNthIpEntity( tcpFile, i, &ent ); tdiGetRoutesForIpEntity( tcpFile, &ent, &route_set, &numRoutes ); if( !route_set ) { closeTcpFile( tcpFile ); HeapFree( GetProcessHeap(), 0, out_route_table ); return 0; } TRACE( "%d routes in instance %d\n", numRoutes, i ); #if 0 HexDump( route_set, sizeof( IPRouteEntry ) * snmpInfo.ipsi_numroutes ); #endif for( j = 0; j < numRoutes; j++ ) { int routeNum = j + routesAdded; out_route_table->routes[routeNum].dest = route_set[j].ire_dest; out_route_table->routes[routeNum].mask = route_set[j].ire_mask; out_route_table->routes[routeNum].gateway = route_set[j].ire_gw; out_route_table->routes[routeNum].ifIndex = route_set[j].ire_index; out_route_table->routes[routeNum].metric = route_set[j].ire_metric1; } if( route_set ) tdiFreeThingSet( route_set ); routesAdded += numRoutes; } closeTcpFile( tcpFile ); TRACE("Return: %08x, %08x\n", status, out_route_table); return out_route_table; }
DWORD WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses( _In_ ULONG Family, _In_ ULONG Flags, _In_ PVOID Reserved, _Inout_ PIP_ADAPTER_ADDRESSES pAdapterAddresses, _Inout_ PULONG pOutBufLen) { NTSTATUS Status; HANDLE TcpFile; TDIEntityID* InterfacesList; ULONG InterfacesCount; ULONG AdaptersCount = 0; ULONG i; ULONG TotalSize = 0, RemainingSize; BYTE* Ptr = (BYTE*)pAdapterAddresses; DWORD MIN_SIZE = 15 * 1024; PIP_ADAPTER_ADDRESSES PreviousAA = NULL; FIXME("GetAdaptersAddresses - Semi Stub: Family %u, Flags 0x%08x, Reserved %p, pAdapterAddress %p, pOutBufLen %p.\n", Family, Flags, Reserved, pAdapterAddresses, pOutBufLen); if (!pOutBufLen) return ERROR_INVALID_PARAMETER; // FIXME: the exact needed size should be computed first, BEFORE doing any write to the output buffer. // As suggested by MSDN, require a 15 KB buffer, which allows to React properly to length checks. if(!Ptr || *pOutBufLen < MIN_SIZE) { *pOutBufLen = MIN_SIZE; return ERROR_BUFFER_OVERFLOW; } switch(Family) { case AF_INET: break; case AF_INET6: /* One day maybe... */ FIXME("IPv6 is not supported in ReactOS!\n"); /* We got nothing to say in this case */ return ERROR_NO_DATA; break; case AF_UNSPEC: WARN("IPv6 addresses ignored, IPv4 only\n"); Family = AF_INET; break; default: ERR("Invalid family 0x%x\n", Family); return ERROR_INVALID_PARAMETER; break; } RemainingSize = *pOutBufLen; if (Ptr) ZeroMemory(Ptr, RemainingSize); /* open the tcpip driver */ Status = openTcpFile(&TcpFile, FILE_READ_DATA); if (!NT_SUCCESS(Status)) { ERR("Could not open handle to tcpip.sys. Status %08x\n", Status); return RtlNtStatusToDosError(Status); } /* Get the interfaces list */ Status = GetInterfacesList(TcpFile, &InterfacesList, &InterfacesCount); if (!NT_SUCCESS(Status)) { ERR("Could not get adapters list. Status %08x\n", Status); NtClose(TcpFile); return RtlNtStatusToDosError(Status); } /* Let's see if we got any adapter. */ for (i = 0; i < InterfacesCount; i++) { PIP_ADAPTER_ADDRESSES CurrentAA = (PIP_ADAPTER_ADDRESSES)Ptr; ULONG CurrentAASize = 0; if (InterfacesList[i].tei_entity == IF_ENTITY) { BYTE EntryBuffer[FIELD_OFFSET(IFEntry, if_descr) + RTL_FIELD_SIZE(IFEntry, if_descr[0]) * (MAX_ADAPTER_DESCRIPTION_LENGTH + 1)]; IFEntry* Entry = (IFEntry*)EntryBuffer; /* Remember we got one */ AdaptersCount++; /* Set the pointer to this instance in the previous one*/ if(PreviousAA) PreviousAA->Next = CurrentAA; /* Of course we need some space for the base structure. */ CurrentAASize = sizeof(IP_ADAPTER_ADDRESSES); /* Get the entry */ Status = GetInterfaceEntry(TcpFile, InterfacesList[i], Entry); if (!NT_SUCCESS(Status)) goto Error; TRACE("Got entity %*s, index %u.\n", Entry->if_descrlen, &Entry->if_descr[0], Entry->if_index); /* Add the adapter name */ CurrentAASize += Entry->if_descrlen + sizeof(CHAR); /* Add the DNS suffix */ CurrentAASize += sizeof(WCHAR); /* Add the description. */ CurrentAASize += sizeof(WCHAR); if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) { /* Just an empty string for now. */ FIXME("Should get adapter friendly name.\n"); CurrentAASize += sizeof(WCHAR); } if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER)) { /* Enumerate the name servers */ HKEY InterfaceKey; CHAR KeyName[256]; snprintf(KeyName, 256, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s", Entry->if_descrlen, &Entry->if_descr[0]); if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) != ERROR_SUCCESS) { ERR("Failed opening interface key for interface %*s\n", Entry->if_descrlen, &Entry->if_descr[0]); Flags |= GAA_FLAG_SKIP_DNS_SERVER; } else { EnumNameServers(InterfaceKey, NULL, &CurrentAASize, EnumerateServerNameSize); RegCloseKey(InterfaceKey); } } /* This is part of what we will need */ TotalSize += CurrentAASize; /* Fill in the data */ if ((CurrentAA) && (RemainingSize >= CurrentAASize)) { CurrentAA->Length = sizeof(IP_ADAPTER_ADDRESSES); CurrentAA->IfIndex = Entry->if_index; CopyMemory(CurrentAA->PhysicalAddress, Entry->if_physaddr, Entry->if_physaddrlen); CurrentAA->PhysicalAddressLength = Entry->if_physaddrlen; CurrentAA->Flags = 0; // FIXME! CurrentAA->Mtu = Entry->if_mtu; CurrentAA->IfType = Entry->if_type; CurrentAA->OperStatus = Entry->if_operstatus; /* Next items */ Ptr = (BYTE*)(CurrentAA + 1); /* Now fill in the name */ CopyMemory(Ptr, &Entry->if_descr[0], Entry->if_descrlen); CurrentAA->AdapterName = (PCHAR)Ptr; CurrentAA->AdapterName[Entry->if_descrlen] = '\0'; /* Next items */ Ptr = (BYTE*)(CurrentAA->AdapterName + Entry->if_descrlen + 1); /* The DNS suffix */ CurrentAA->DnsSuffix = (PWCHAR)Ptr; CurrentAA->DnsSuffix[0] = L'\0'; /* Next items */ Ptr = (BYTE*)(CurrentAA->DnsSuffix + 1); /* The description */ CurrentAA->Description = (PWCHAR)Ptr; CurrentAA->Description[0] = L'\0'; /* Next items */ Ptr = (BYTE*)(CurrentAA->Description + 1); /* The friendly name */ if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) { CurrentAA->FriendlyName = (PWCHAR)Ptr; CurrentAA->FriendlyName[0] = L'\0'; /* Next items */ Ptr = (BYTE*)(CurrentAA->FriendlyName + 1); } /* The DNS Servers */ if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER)) { /* Enumerate the name servers */ HKEY InterfaceKey; CHAR KeyName[256]; snprintf(KeyName, 256, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s", Entry->if_descrlen, &Entry->if_descr[0]); if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) != ERROR_SUCCESS) { ERR("Failed opening interface key for interface %*s\n", Entry->if_descrlen, &Entry->if_descr[0]); } else { PIP_ADAPTER_DNS_SERVER_ADDRESS* ServerAddressPtr; CurrentAA->FirstDnsServerAddress = (PIP_ADAPTER_DNS_SERVER_ADDRESS)Ptr; ServerAddressPtr = &CurrentAA->FirstDnsServerAddress; EnumNameServers(InterfaceKey, NULL, &ServerAddressPtr, EnumerateServerName); RegCloseKey(InterfaceKey); /* Set the last entry in the list as having NULL next member */ Ptr = (BYTE*)*ServerAddressPtr; *ServerAddressPtr = NULL; } } /* We're done for this interface */ PreviousAA = CurrentAA; RemainingSize -= CurrentAASize; } } } if (AdaptersCount == 0) { /* Uh? Not even localhost ?! */ ERR("No Adapters found!\n"); *pOutBufLen = 0; return ERROR_NO_DATA; } /* See if we have anything to add */ // FIXME: Anycast and multicast if ((Flags & (GAA_FLAG_SKIP_UNICAST | GAA_FLAG_INCLUDE_PREFIX)) == GAA_FLAG_SKIP_UNICAST) goto Success; /* Now fill in the addresses */ for (i = 0; i < InterfacesCount; i++) { /* Look for network layers */ if ((InterfacesList[i].tei_entity == CL_NL_ENTITY) || (InterfacesList[i].tei_entity == CO_NL_ENTITY)) { IPSNMPInfo SnmpInfo; PIP_ADAPTER_ADDRESSES CurrentAA = NULL; IPAddrEntry* AddrEntries; ULONG j; /* Get its SNMP info */ Status = GetSnmpInfo(TcpFile, InterfacesList[i], &SnmpInfo); if (!NT_SUCCESS(Status)) goto Error; if (SnmpInfo.ipsi_numaddr == 0) continue; /* Allocate the address entry array and get them */ AddrEntries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SnmpInfo.ipsi_numaddr * sizeof(AddrEntries[0])); if (!AddrEntries) { Status = STATUS_NO_MEMORY; goto Error; } Status = GetAddrEntries(TcpFile, InterfacesList[i], AddrEntries, SnmpInfo.ipsi_numaddr); if (!NT_SUCCESS(Status)) { HeapFree(GetProcessHeap(), 0, AddrEntries); goto Error; } for (j = 0; j < SnmpInfo.ipsi_numaddr; j++) { /* Find the adapters struct for this address. */ if (pAdapterAddresses) { CurrentAA = pAdapterAddresses; while (CurrentAA) { if (CurrentAA->IfIndex == AddrEntries[j].iae_index) break; CurrentAA = CurrentAA->Next; } if (!CurrentAA) { ERR("Got address for interface %u but no adapter was found for it.\n", AddrEntries[j].iae_index); /* Go to the next address */ continue; } } ERR("address is 0x%08x, mask is 0x%08x\n", AddrEntries[j].iae_addr, AddrEntries[j].iae_mask); //FIXME: For now reactos only supports unicast addresses if (!(Flags & GAA_FLAG_SKIP_UNICAST)) { ULONG Size = sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR); if (Ptr && (RemainingSize >= Size)) { PIP_ADAPTER_UNICAST_ADDRESS UnicastAddress = (PIP_ADAPTER_UNICAST_ADDRESS)Ptr; /* Fill in the structure */ UnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS); UnicastAddress->Next = CurrentAA->FirstUnicastAddress; // FIXME: Put meaningful value here UnicastAddress->Flags = 0; UnicastAddress->PrefixOrigin = IpPrefixOriginOther; UnicastAddress->SuffixOrigin = IpSuffixOriginOther; UnicastAddress->DadState = IpDadStatePreferred; UnicastAddress->ValidLifetime = 0xFFFFFFFF; UnicastAddress->PreferredLifetime = 0xFFFFFFFF; /* Set the address */ //FIXME: ipv4 only (again...) UnicastAddress->Address.lpSockaddr = (LPSOCKADDR)(UnicastAddress + 1); UnicastAddress->Address.iSockaddrLength = sizeof(AddrEntries[j].iae_addr); UnicastAddress->Address.lpSockaddr->sa_family = AF_INET; memcpy(UnicastAddress->Address.lpSockaddr->sa_data, &AddrEntries[j].iae_addr, sizeof(AddrEntries[j].iae_addr)); CurrentAA->FirstUnicastAddress = UnicastAddress; Ptr += Size; RemainingSize -= Size; } TotalSize += Size; } if (Flags & GAA_FLAG_INCLUDE_PREFIX) { ULONG Size = sizeof(IP_ADAPTER_PREFIX) + sizeof(SOCKADDR); if (Ptr && (RemainingSize >= Size)) { PIP_ADAPTER_PREFIX Prefix = (PIP_ADAPTER_PREFIX)Ptr; /* Fill in the structure */ Prefix->Length = sizeof(IP_ADAPTER_PREFIX); Prefix->Next = CurrentAA->FirstPrefix; /* Set the address */ //FIXME: ipv4 only (again...) Prefix->Address.lpSockaddr = (LPSOCKADDR)(Prefix + 1); Prefix->Address.iSockaddrLength = sizeof(AddrEntries[j].iae_mask); Prefix->Address.lpSockaddr->sa_family = AF_INET; memcpy(Prefix->Address.lpSockaddr->sa_data, &AddrEntries[j].iae_mask, sizeof(AddrEntries[j].iae_mask)); /* Compute the prefix size */ _BitScanReverse(&Prefix->PrefixLength, AddrEntries[j].iae_mask); CurrentAA->FirstPrefix = Prefix; Ptr += Size; RemainingSize -= Size; } TotalSize += Size; } } HeapFree(GetProcessHeap(), 0, AddrEntries); } } Success: /* We're done */ HeapFree(GetProcessHeap(), 0, InterfacesList); NtClose(TcpFile); *pOutBufLen = TotalSize; TRACE("TotalSize: %x\n", *pOutBufLen); return ERROR_SUCCESS; Error: ERR("Failed! Status 0x%08x\n", Status); *pOutBufLen = 0; HeapFree(GetProcessHeap(), 0, InterfacesList); NtClose(TcpFile); return RtlNtStatusToDosError(Status); }