1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: dll/win32/iphlpapi/address.c 5 * PURPOSE: iphlpapi implementation - Adapter Address APIs 6 * PROGRAMMERS: Jérôme Gardou (jerome.gardou@reactos.org) 7 */ 8 9 #include "iphlpapi_private.h" 10 11 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); 12 #ifdef GetAdaptersAddressesV2 13 /* Helper for GetAdaptersAddresses: 14 * Retrieves the list of network adapters from tcpip.sys */ 15 static 16 NTSTATUS 17 GetInterfacesList( 18 _In_ HANDLE TcpFile, 19 _Out_ TDIEntityID **EntityList, 20 _Out_ ULONG* InterfaceCount) 21 { 22 23 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo; 24 IO_STATUS_BLOCK StatusBlock; 25 NTSTATUS Status; 26 ULONG_PTR BufferSize; 27 28 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo)); 29 TcpQueryInfo.ID.toi_class = INFO_CLASS_GENERIC; 30 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER; 31 TcpQueryInfo.ID.toi_id = ENTITY_LIST_ID; 32 TcpQueryInfo.ID.toi_entity.tei_entity = GENERIC_ENTITY; 33 TcpQueryInfo.ID.toi_entity.tei_instance = 0; 34 35 Status = NtDeviceIoControlFile( 36 TcpFile, 37 NULL, 38 NULL, 39 NULL, 40 &StatusBlock, 41 IOCTL_TCP_QUERY_INFORMATION_EX, 42 &TcpQueryInfo, 43 sizeof(TcpQueryInfo), 44 NULL, 45 0); 46 if (Status == STATUS_PENDING) 47 { 48 /* So we have to wait a bit */ 49 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL); 50 if (NT_SUCCESS(Status)) 51 Status = StatusBlock.Status; 52 } 53 54 if (!NT_SUCCESS(Status)) 55 return Status; 56 57 BufferSize = StatusBlock.Information; 58 *EntityList = HeapAlloc(GetProcessHeap(), 0, BufferSize); 59 if (!*EntityList) 60 return STATUS_NO_MEMORY; 61 62 /* Do the real call */ 63 Status = NtDeviceIoControlFile( 64 TcpFile, 65 NULL, 66 NULL, 67 NULL, 68 &StatusBlock, 69 IOCTL_TCP_QUERY_INFORMATION_EX, 70 &TcpQueryInfo, 71 sizeof(TcpQueryInfo), 72 *EntityList, 73 BufferSize); 74 if (Status == STATUS_PENDING) 75 { 76 /* So we have to wait a bit */ 77 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL); 78 if (NT_SUCCESS(Status)) 79 Status = StatusBlock.Status; 80 } 81 82 if (!NT_SUCCESS(Status)) 83 { 84 HeapFree(GetProcessHeap(), 0, *EntityList); 85 return Status; 86 } 87 88 *InterfaceCount = BufferSize / sizeof(TDIEntityID); 89 return Status; 90 } 91 92 static 93 NTSTATUS 94 GetSnmpInfo( 95 _In_ HANDLE TcpFile, 96 _In_ TDIEntityID InterfaceID, 97 _Out_ IPSNMPInfo* Info) 98 { 99 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo; 100 IO_STATUS_BLOCK StatusBlock; 101 NTSTATUS Status; 102 103 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo)); 104 TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL; 105 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER; 106 TcpQueryInfo.ID.toi_id = IP_MIB_STATS_ID; 107 TcpQueryInfo.ID.toi_entity = InterfaceID; 108 109 Status = NtDeviceIoControlFile( 110 TcpFile, 111 NULL, 112 NULL, 113 NULL, 114 &StatusBlock, 115 IOCTL_TCP_QUERY_INFORMATION_EX, 116 &TcpQueryInfo, 117 sizeof(TcpQueryInfo), 118 Info, 119 sizeof(*Info)); 120 if (Status == STATUS_PENDING) 121 { 122 /* So we have to wait a bit */ 123 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL); 124 if (NT_SUCCESS(Status)) 125 Status = StatusBlock.Status; 126 } 127 128 return Status; 129 } 130 131 static 132 NTSTATUS 133 GetAddrEntries( 134 _In_ HANDLE TcpFile, 135 _In_ TDIEntityID InterfaceID, 136 _Out_ IPAddrEntry* Entries, 137 _In_ ULONG NumEntries) 138 { 139 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo; 140 IO_STATUS_BLOCK StatusBlock; 141 NTSTATUS Status; 142 143 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo)); 144 TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL; 145 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER; 146 TcpQueryInfo.ID.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID; 147 TcpQueryInfo.ID.toi_entity = InterfaceID; 148 149 Status = NtDeviceIoControlFile( 150 TcpFile, 151 NULL, 152 NULL, 153 NULL, 154 &StatusBlock, 155 IOCTL_TCP_QUERY_INFORMATION_EX, 156 &TcpQueryInfo, 157 sizeof(TcpQueryInfo), 158 Entries, 159 NumEntries * sizeof(Entries[0])); 160 if (Status == STATUS_PENDING) 161 { 162 /* So we have to wait a bit */ 163 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL); 164 if (NT_SUCCESS(Status)) 165 Status = StatusBlock.Status; 166 } 167 168 return Status; 169 } 170 171 /* 172 * Fills the IFEntry buffer from tcpip.sys. 173 * The buffer size MUST be FIELD_OFFSET(IFEntry, if_descr[MAX_ADAPTER_DESCRIPTION_LENGTH + 1]). 174 * See MSDN IFEntry struct definition if you don't believe me. ;-) 175 */ 176 static 177 NTSTATUS 178 GetInterfaceEntry( 179 _In_ HANDLE TcpFile, 180 _In_ TDIEntityID InterfaceID, 181 _Out_ IFEntry* Entry) 182 { 183 TCP_REQUEST_QUERY_INFORMATION_EX TcpQueryInfo; 184 IO_STATUS_BLOCK StatusBlock; 185 NTSTATUS Status; 186 187 ZeroMemory(&TcpQueryInfo, sizeof(TcpQueryInfo)); 188 TcpQueryInfo.ID.toi_class = INFO_CLASS_PROTOCOL; 189 TcpQueryInfo.ID.toi_type = INFO_TYPE_PROVIDER; 190 TcpQueryInfo.ID.toi_id = IP_MIB_STATS_ID; 191 TcpQueryInfo.ID.toi_entity = InterfaceID; 192 193 Status = NtDeviceIoControlFile( 194 TcpFile, 195 NULL, 196 NULL, 197 NULL, 198 &StatusBlock, 199 IOCTL_TCP_QUERY_INFORMATION_EX, 200 &TcpQueryInfo, 201 sizeof(TcpQueryInfo), 202 Entry, 203 FIELD_OFFSET(IFEntry, if_descr[MAX_ADAPTER_DESCRIPTION_LENGTH + 1])); 204 if (Status == STATUS_PENDING) 205 { 206 /* So we have to wait a bit */ 207 Status = NtWaitForSingleObject(TcpFile, FALSE, NULL); 208 if (NT_SUCCESS(Status)) 209 Status = StatusBlock.Status; 210 } 211 212 return Status; 213 } 214 215 /* Helpers to get the list of DNS for an interface */ 216 static 217 VOID 218 EnumerateServerNameSize( 219 _In_ PWCHAR Interface, 220 _In_ PWCHAR NameServer, 221 _Inout_ PVOID Data) 222 { 223 ULONG* BufferSize = Data; 224 225 /* This is just sizing here */ 226 UNREFERENCED_PARAMETER(Interface); 227 UNREFERENCED_PARAMETER(NameServer); 228 229 *BufferSize += sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS) + sizeof(SOCKADDR); 230 } 231 232 static 233 VOID 234 EnumerateServerName( 235 _In_ PWCHAR Interface, 236 _In_ PWCHAR NameServer, 237 _Inout_ PVOID Data) 238 { 239 PIP_ADAPTER_DNS_SERVER_ADDRESS** Ptr = Data; 240 PIP_ADAPTER_DNS_SERVER_ADDRESS ServerAddress = **Ptr; 241 242 UNREFERENCED_PARAMETER(Interface); 243 244 ServerAddress->Length = sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS); 245 ServerAddress->Address.lpSockaddr = (PVOID)(ServerAddress + 1); 246 ServerAddress->Address.iSockaddrLength = sizeof(SOCKADDR); 247 248 249 /* Get the address from the server name string */ 250 //FIXME: Only ipv4 for now... 251 if (WSAStringToAddressW( 252 NameServer, 253 AF_INET, 254 NULL, 255 ServerAddress->Address.lpSockaddr, 256 &ServerAddress->Address.iSockaddrLength)) 257 { 258 /* Pass along, name conversion failed */ 259 ERR("%S is not a valid IP address\n", NameServer); 260 return; 261 } 262 263 /* Go to next item */ 264 ServerAddress->Next = (PVOID)(ServerAddress->Address.lpSockaddr + 1); 265 *Ptr = &ServerAddress->Next; 266 } 267 268 static 269 VOID 270 QueryFlags( 271 _In_ PUCHAR Interface, 272 _In_ DWORD InterfaceLength, 273 _Out_ LPDWORD Flags) 274 { 275 HKEY InterfaceKey; 276 CHAR KeyName[256]; 277 DWORD Type, Size, Data; 278 279 *Flags = 0; 280 281 snprintf(KeyName, 256, 282 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s", 283 InterfaceLength, Interface); 284 285 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) == ERROR_SUCCESS) 286 { 287 Size = sizeof(DWORD); 288 if (RegQueryValueExA(InterfaceKey, "EnableDHCP", NULL, &Type, (LPBYTE)&Data, &Size) == ERROR_SUCCESS && 289 Type == REG_DWORD && Data == 1) 290 { 291 *Flags |= IP_ADAPTER_DHCP_ENABLED; 292 } 293 294 Size = sizeof(DWORD); 295 if (RegQueryValueExA(InterfaceKey, "RegisterAdapterName", NULL, &Type, (LPBYTE)&Data, &Size) == ERROR_SUCCESS && 296 Type == REG_DWORD && Data == 1) 297 { 298 *Flags |= IP_ADAPTER_REGISTER_ADAPTER_SUFFIX; 299 } 300 301 Size = 0; 302 if (RegQueryValueExA(InterfaceKey, "NameServer", NULL, &Type, (LPBYTE)&Data, &Size) != ERROR_SUCCESS) 303 { 304 *Flags |= IP_ADAPTER_DDNS_ENABLED; 305 } 306 307 RegCloseKey(InterfaceKey); 308 } 309 310 // FIXME: handle 0x8 -> 0x20 311 } 312 313 DWORD 314 WINAPI 315 DECLSPEC_HOTPATCH 316 GetAdaptersAddresses( 317 _In_ ULONG Family, 318 _In_ ULONG Flags, 319 _In_ PVOID Reserved, 320 _Inout_ PIP_ADAPTER_ADDRESSES pAdapterAddresses, 321 _Inout_ PULONG pOutBufLen) 322 { 323 NTSTATUS Status; 324 HANDLE TcpFile; 325 TDIEntityID* InterfacesList; 326 ULONG InterfacesCount; 327 ULONG AdaptersCount = 0; 328 ULONG i; 329 ULONG TotalSize = 0, RemainingSize; 330 BYTE* Ptr = (BYTE*)pAdapterAddresses; 331 DWORD MIN_SIZE = 15 * 1024; 332 PIP_ADAPTER_ADDRESSES PreviousAA = NULL; 333 334 TRACE("Family %u, Flags 0x%08x, Reserved %p, pAdapterAddress %p, pOutBufLen %p\n", 335 Family, Flags, Reserved, pAdapterAddresses, pOutBufLen); 336 337 if (!pOutBufLen) 338 return ERROR_INVALID_PARAMETER; 339 340 // FIXME: the exact needed size should be computed first, BEFORE doing any write to the output buffer. 341 // As suggested by MSDN, require a 15 KB buffer, which allows to React properly to length checks. 342 if(!Ptr || *pOutBufLen < MIN_SIZE) 343 { 344 *pOutBufLen = MIN_SIZE; 345 return ERROR_BUFFER_OVERFLOW; 346 } 347 348 switch(Family) 349 { 350 case AF_INET: 351 break; 352 case AF_INET6: 353 /* One day maybe... */ 354 FIXME("IPv6 is not supported in ReactOS!\n"); 355 /* We got nothing to say in this case */ 356 return ERROR_NO_DATA; 357 break; 358 case AF_UNSPEC: 359 WARN("IPv6 addresses ignored, IPv4 only\n"); 360 Family = AF_INET; 361 break; 362 default: 363 ERR("Invalid family 0x%x\n", Family); 364 return ERROR_INVALID_PARAMETER; 365 break; 366 } 367 368 RemainingSize = *pOutBufLen; 369 if (Ptr) 370 ZeroMemory(Ptr, RemainingSize); 371 372 /* open the tcpip driver */ 373 Status = openTcpFile(&TcpFile, FILE_READ_DATA); 374 if (!NT_SUCCESS(Status)) 375 { 376 ERR("Could not open handle to tcpip.sys. Status %08x\n", Status); 377 return RtlNtStatusToDosError(Status); 378 } 379 380 /* Get the interfaces list */ 381 Status = GetInterfacesList(TcpFile, &InterfacesList, &InterfacesCount); 382 if (!NT_SUCCESS(Status)) 383 { 384 ERR("Could not get adapters list. Status %08x\n", Status); 385 NtClose(TcpFile); 386 return RtlNtStatusToDosError(Status); 387 } 388 389 /* Let's see if we got any adapter. */ 390 for (i = 0; i < InterfacesCount; i++) 391 { 392 PIP_ADAPTER_ADDRESSES CurrentAA = (PIP_ADAPTER_ADDRESSES)Ptr; 393 ULONG CurrentAASize = 0; 394 ULONG FriendlySize = 0; 395 396 if (InterfacesList[i].tei_entity == IF_ENTITY) 397 { 398 BYTE EntryBuffer[FIELD_OFFSET(IFEntry, if_descr) + 399 RTL_FIELD_SIZE(IFEntry, if_descr[0]) * (MAX_ADAPTER_DESCRIPTION_LENGTH + 1)]; 400 IFEntry* Entry = (IFEntry*)EntryBuffer; 401 402 /* Remember we got one */ 403 AdaptersCount++; 404 405 /* Set the pointer to this instance in the previous one*/ 406 if(PreviousAA) 407 PreviousAA->Next = CurrentAA; 408 409 /* Of course we need some space for the base structure. */ 410 CurrentAASize = sizeof(IP_ADAPTER_ADDRESSES); 411 412 /* Get the entry */ 413 Status = GetInterfaceEntry(TcpFile, InterfacesList[i], Entry); 414 if (!NT_SUCCESS(Status)) 415 goto Error; 416 417 TRACE("Got entity %*s, index %u.\n", 418 Entry->if_descrlen, &Entry->if_descr[0], Entry->if_index); 419 420 /* Add the adapter name */ 421 CurrentAASize += Entry->if_descrlen + sizeof(CHAR); 422 423 /* Add the DNS suffix */ 424 CurrentAASize += sizeof(WCHAR); 425 426 /* Add the description. */ 427 CurrentAASize += sizeof(WCHAR); 428 429 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) 430 { 431 /* Get the friendly name */ 432 HKEY ConnectionKey; 433 CHAR KeyName[256]; 434 435 snprintf(KeyName, 256, 436 "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%*s\\Connection", 437 Entry->if_descrlen, &Entry->if_descr[0]); 438 439 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &ConnectionKey) == ERROR_SUCCESS) 440 { 441 DWORD ValueType; 442 DWORD ValueSize = 0; 443 444 if (RegQueryValueExW(ConnectionKey, L"Name", NULL, &ValueType, NULL, &ValueSize) == ERROR_SUCCESS && 445 ValueType == REG_SZ) 446 { 447 /* We remove the null char, it will be re-added after */ 448 FriendlySize = ValueSize - sizeof(WCHAR); 449 CurrentAASize += FriendlySize; 450 } 451 452 RegCloseKey(ConnectionKey); 453 } 454 455 /* We always make sure to have enough room for empty string */ 456 CurrentAASize += sizeof(WCHAR); 457 } 458 459 if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER)) 460 { 461 /* Enumerate the name servers */ 462 HKEY InterfaceKey; 463 CHAR KeyName[256]; 464 465 snprintf(KeyName, 256, 466 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s", 467 Entry->if_descrlen, &Entry->if_descr[0]); 468 469 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) == ERROR_SUCCESS) 470 { 471 EnumNameServers(InterfaceKey, NULL, &CurrentAASize, EnumerateServerNameSize); 472 RegCloseKey(InterfaceKey); 473 } 474 } 475 476 /* This is part of what we will need */ 477 TotalSize += CurrentAASize; 478 479 /* Fill in the data */ 480 if ((CurrentAA) && (RemainingSize >= CurrentAASize)) 481 { 482 CurrentAA->Length = sizeof(IP_ADAPTER_ADDRESSES); 483 CurrentAA->IfIndex = Entry->if_index; 484 CopyMemory(CurrentAA->PhysicalAddress, Entry->if_physaddr, Entry->if_physaddrlen); 485 CurrentAA->PhysicalAddressLength = Entry->if_physaddrlen; 486 QueryFlags(&Entry->if_descr[0], Entry->if_descrlen, &CurrentAA->Flags); 487 CurrentAA->Mtu = Entry->if_mtu; 488 CurrentAA->IfType = Entry->if_type; 489 if(Entry->if_operstatus >= IF_OPER_STATUS_CONNECTING) 490 CurrentAA->OperStatus = IfOperStatusUp; 491 else 492 CurrentAA->OperStatus = IfOperStatusDown; 493 494 /* Next items */ 495 Ptr = (BYTE*)(CurrentAA + 1); 496 497 /* Now fill in the name */ 498 CopyMemory(Ptr, &Entry->if_descr[0], Entry->if_descrlen); 499 CurrentAA->AdapterName = (PCHAR)Ptr; 500 CurrentAA->AdapterName[Entry->if_descrlen] = '\0'; 501 /* Next items */ 502 Ptr = (BYTE*)(CurrentAA->AdapterName + Entry->if_descrlen + 1); 503 504 /* The DNS suffix */ 505 CurrentAA->DnsSuffix = (PWCHAR)Ptr; 506 CurrentAA->DnsSuffix[0] = L'\0'; 507 /* Next items */ 508 Ptr = (BYTE*)(CurrentAA->DnsSuffix + 1); 509 510 /* The description */ 511 CurrentAA->Description = (PWCHAR)Ptr; 512 CurrentAA->Description[0] = L'\0'; 513 /* Next items */ 514 Ptr = (BYTE*)(CurrentAA->Description + 1); 515 516 /* The friendly name */ 517 if (!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) 518 { 519 CurrentAA->FriendlyName = (PWCHAR)Ptr; 520 521 if (FriendlySize != 0) 522 { 523 /* Get the friendly name */ 524 HKEY ConnectionKey; 525 CHAR KeyName[256]; 526 527 snprintf(KeyName, 256, 528 "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%*s\\Connection", 529 Entry->if_descrlen, &Entry->if_descr[0]); 530 531 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &ConnectionKey) == ERROR_SUCCESS) 532 { 533 DWORD ValueType; 534 DWORD ValueSize = FriendlySize + sizeof(WCHAR); 535 536 if (RegQueryValueExW(ConnectionKey, L"Name", NULL, &ValueType, (LPBYTE)CurrentAA->FriendlyName, &ValueSize) == ERROR_SUCCESS && 537 ValueType == REG_SZ && ValueSize == FriendlySize + sizeof(WCHAR)) 538 { 539 /* We're done, next items */ 540 Ptr = (BYTE*)(CurrentAA->FriendlyName + (ValueSize / sizeof(WCHAR))); 541 } 542 else 543 { 544 /* Fail */ 545 ERR("Friendly name changed after probe!\n"); 546 FriendlySize = 0; 547 } 548 549 RegCloseKey(ConnectionKey); 550 } 551 else 552 { 553 /* Fail */ 554 FriendlySize = 0; 555 } 556 } 557 558 /* In case of failure (or no name) */ 559 if (FriendlySize == 0) 560 { 561 CurrentAA->FriendlyName[0] = L'\0'; 562 /* Next items */ 563 Ptr = (BYTE*)(CurrentAA->FriendlyName + 1); 564 } 565 } 566 567 /* The DNS Servers */ 568 if (!(Flags & GAA_FLAG_SKIP_DNS_SERVER)) 569 { 570 /* Enumerate the name servers */ 571 HKEY InterfaceKey; 572 CHAR KeyName[256]; 573 574 snprintf(KeyName, 256, 575 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%*s", 576 Entry->if_descrlen, &Entry->if_descr[0]); 577 578 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &InterfaceKey) != ERROR_SUCCESS) 579 { 580 TRACE("Failed opening interface key for interface %*s\n", Entry->if_descrlen, &Entry->if_descr[0]); 581 } 582 else 583 { 584 PIP_ADAPTER_DNS_SERVER_ADDRESS* ServerAddressPtr; 585 586 CurrentAA->FirstDnsServerAddress = (PIP_ADAPTER_DNS_SERVER_ADDRESS)Ptr; 587 ServerAddressPtr = &CurrentAA->FirstDnsServerAddress; 588 589 EnumNameServers(InterfaceKey, NULL, &ServerAddressPtr, EnumerateServerName); 590 RegCloseKey(InterfaceKey); 591 592 /* Set the last entry in the list as having NULL next member */ 593 Ptr = (BYTE*)*ServerAddressPtr; 594 *ServerAddressPtr = NULL; 595 } 596 } 597 598 /* We're done for this interface */ 599 PreviousAA = CurrentAA; 600 RemainingSize -= CurrentAASize; 601 } 602 } 603 } 604 605 if (AdaptersCount == 0) 606 { 607 /* Uh? Not even localhost ?! */ 608 ERR("No Adapters found!\n"); 609 *pOutBufLen = 0; 610 return ERROR_NO_DATA; 611 } 612 613 /* See if we have anything to add */ 614 // FIXME: Anycast and multicast 615 if ((Flags & (GAA_FLAG_SKIP_UNICAST | GAA_FLAG_INCLUDE_PREFIX)) == GAA_FLAG_SKIP_UNICAST) 616 goto Success; 617 618 /* Now fill in the addresses */ 619 for (i = 0; i < InterfacesCount; i++) 620 { 621 /* Look for network layers */ 622 if ((InterfacesList[i].tei_entity == CL_NL_ENTITY) 623 || (InterfacesList[i].tei_entity == CO_NL_ENTITY)) 624 { 625 IPSNMPInfo SnmpInfo; 626 PIP_ADAPTER_ADDRESSES CurrentAA = NULL; 627 IPAddrEntry* AddrEntries; 628 ULONG j; 629 630 /* Get its SNMP info */ 631 Status = GetSnmpInfo(TcpFile, InterfacesList[i], &SnmpInfo); 632 if (!NT_SUCCESS(Status)) 633 goto Error; 634 635 if (SnmpInfo.ipsi_numaddr == 0) 636 continue; 637 638 /* Allocate the address entry array and get them */ 639 AddrEntries = HeapAlloc(GetProcessHeap(), 640 HEAP_ZERO_MEMORY, 641 SnmpInfo.ipsi_numaddr * sizeof(AddrEntries[0])); 642 if (!AddrEntries) 643 { 644 Status = STATUS_NO_MEMORY; 645 goto Error; 646 } 647 Status = GetAddrEntries(TcpFile, InterfacesList[i], AddrEntries, SnmpInfo.ipsi_numaddr); 648 if (!NT_SUCCESS(Status)) 649 { 650 HeapFree(GetProcessHeap(), 0, AddrEntries); 651 goto Error; 652 } 653 654 for (j = 0; j < SnmpInfo.ipsi_numaddr; j++) 655 { 656 /* Find the adapters struct for this address. */ 657 if (pAdapterAddresses) 658 { 659 CurrentAA = pAdapterAddresses; 660 while (CurrentAA) 661 { 662 if (CurrentAA->IfIndex == AddrEntries[j].iae_index) 663 break; 664 665 CurrentAA = CurrentAA->Next; 666 } 667 668 if (!CurrentAA) 669 { 670 ERR("Got address for interface %u but no adapter was found for it.\n", AddrEntries[j].iae_index); 671 /* Go to the next address */ 672 continue; 673 } 674 } 675 676 TRACE("address is 0x%08x, mask is 0x%08x\n", AddrEntries[j].iae_addr, AddrEntries[j].iae_mask); 677 678 //FIXME: For now reactos only supports unicast addresses 679 if (!(Flags & GAA_FLAG_SKIP_UNICAST)) 680 { 681 ULONG Size = sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR); 682 683 if (Ptr && (RemainingSize >= Size)) 684 { 685 PIP_ADAPTER_UNICAST_ADDRESS UnicastAddress = (PIP_ADAPTER_UNICAST_ADDRESS)Ptr; 686 687 /* Fill in the structure */ 688 UnicastAddress->Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS); 689 UnicastAddress->Next = CurrentAA->FirstUnicastAddress; 690 691 // FIXME: Put meaningful value here 692 UnicastAddress->Flags = 0; 693 UnicastAddress->PrefixOrigin = IpPrefixOriginOther; 694 UnicastAddress->SuffixOrigin = IpSuffixOriginOther; 695 UnicastAddress->DadState = IpDadStatePreferred; 696 UnicastAddress->ValidLifetime = 0xFFFFFFFF; 697 UnicastAddress->PreferredLifetime = 0xFFFFFFFF; 698 699 /* Set the address */ 700 //FIXME: ipv4 only (again...) 701 UnicastAddress->Address.lpSockaddr = (LPSOCKADDR)(UnicastAddress + 1); 702 UnicastAddress->Address.iSockaddrLength = sizeof(SOCKADDR); 703 UnicastAddress->Address.lpSockaddr->sa_family = AF_INET; 704 ((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_port = 0; 705 memcpy(&((LPSOCKADDR_IN)UnicastAddress->Address.lpSockaddr)->sin_addr, &AddrEntries[j].iae_addr, sizeof(AddrEntries[j].iae_addr)); 706 707 CurrentAA->FirstUnicastAddress = UnicastAddress; 708 Ptr += Size; 709 RemainingSize -= Size; 710 } 711 712 TotalSize += Size; 713 } 714 715 if (Flags & GAA_FLAG_INCLUDE_PREFIX) 716 { 717 ULONG Size = sizeof(IP_ADAPTER_PREFIX) + sizeof(SOCKADDR); 718 719 if (Ptr && (RemainingSize >= Size)) 720 { 721 PIP_ADAPTER_PREFIX Prefix = (PIP_ADAPTER_PREFIX)Ptr; 722 723 /* Fill in the structure */ 724 Prefix->Length = sizeof(IP_ADAPTER_PREFIX); 725 Prefix->Next = CurrentAA->FirstPrefix; 726 727 /* Set the address */ 728 //FIXME: ipv4 only (again...) 729 Prefix->Address.lpSockaddr = (LPSOCKADDR)(Prefix + 1); 730 Prefix->Address.iSockaddrLength = sizeof(AddrEntries[j].iae_mask); 731 Prefix->Address.lpSockaddr->sa_family = AF_INET; 732 memcpy(Prefix->Address.lpSockaddr->sa_data, &AddrEntries[j].iae_mask, sizeof(AddrEntries[j].iae_mask)); 733 734 /* Compute the prefix size */ 735 _BitScanReverse(&Prefix->PrefixLength, AddrEntries[j].iae_mask); 736 737 CurrentAA->FirstPrefix = Prefix; 738 Ptr += Size; 739 RemainingSize -= Size; 740 } 741 742 TotalSize += Size; 743 } 744 } 745 746 HeapFree(GetProcessHeap(), 0, AddrEntries); 747 } 748 } 749 750 Success: 751 /* We're done */ 752 HeapFree(GetProcessHeap(), 0, InterfacesList); 753 NtClose(TcpFile); 754 *pOutBufLen = TotalSize; 755 TRACE("TotalSize: %x\n", *pOutBufLen); 756 return ERROR_SUCCESS; 757 758 Error: 759 ERR("Failed! Status 0x%08x\n", Status); 760 *pOutBufLen = 0; 761 HeapFree(GetProcessHeap(), 0, InterfacesList); 762 NtClose(TcpFile); 763 return RtlNtStatusToDosError(Status); 764 } 765 #endif 766