From f679ffe173d59a28f49f2db35d4a3086c38c7e27 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 14 Jan 2012 19:42:58 +0000 Subject: [PATCH] - Merge 54929, 54930, 54932, 54933, 54934, 54939, 54941, 54942, 54944, 54945, 54946, and 54947 - The DHCP service now recognizes adapter configuration and media state changes without manual intervention - Multiple bugs with a static IP configuration are fixed - IpRenewAddress (ipconfig /renew) and IpReleaseAddress (ipconfig /release) no longer corrupt internal DHCP state - Routes that cannot currently be resolved by ARP no longer become corrupted by the neighbor timeout svn path=/trunk/; revision=54966 --- reactos/dll/win32/dhcpcsvc/dhcp/adapter.c | 104 +++- reactos/dll/win32/dhcpcsvc/dhcp/api.c | 12 + reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c | 16 +- reactos/dll/win32/iphlpapi/iphlpapi_main.c | 3 +- reactos/dll/win32/netcfgx/tcpipconf_notify.c | 24 +- reactos/drivers/network/tcpip/datalink/lan.c | 543 +++++++++++------- reactos/drivers/network/tcpip/include/ip.h | 1 - reactos/drivers/network/tcpip/include/lan.h | 3 +- .../drivers/network/tcpip/include/neighbor.h | 11 +- .../drivers/network/tcpip/include/router.h | 2 + .../drivers/network/tcpip/tcpip/dispatch.c | 5 + reactos/lib/drivers/ip/network/ip.c | 6 - reactos/lib/drivers/ip/network/loopback.c | 5 +- reactos/lib/drivers/ip/network/neighbor.c | 72 ++- reactos/lib/drivers/ip/network/router.c | 33 +- 15 files changed, 570 insertions(+), 270 deletions(-) diff --git a/reactos/dll/win32/dhcpcsvc/dhcp/adapter.c b/reactos/dll/win32/dhcpcsvc/dhcp/adapter.c index d79b76b112b..2888db16a87 100644 --- a/reactos/dll/win32/dhcpcsvc/dhcp/adapter.c +++ b/reactos/dll/win32/dhcpcsvc/dhcp/adapter.c @@ -200,6 +200,85 @@ InterfaceConnected(const MIB_IFROW* IfEntry) return 0; } +BOOL +IsReconnectHackNeeded(PDHCP_ADAPTER Adapter, const MIB_IFROW* IfEntry) +{ + struct protocol *proto; + PIP_ADAPTER_INFO AdapterInfo, Orig; + DWORD Size, Ret; + char *ZeroAddress = "0.0.0.0"; + + proto = find_protocol_by_adapter(&Adapter->DhclientInfo); + + if (Adapter->DhclientInfo.client->state == S_BOUND && !proto) + return FALSE; + + if (Adapter->DhclientInfo.client->state != S_BOUND && + Adapter->DhclientInfo.client->state != S_STATIC) + return FALSE; + + ApiUnlock(); + + Orig = AdapterInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO)); + Size = sizeof(IP_ADAPTER_INFO); + if (!AdapterInfo) + { + ApiLock(); + return FALSE; + } + + Ret = GetAdaptersInfo(AdapterInfo, &Size); + if (Ret == ERROR_BUFFER_OVERFLOW) + { + HeapFree(GetProcessHeap(), 0, AdapterInfo); + AdapterInfo = HeapAlloc(GetProcessHeap(), 0, Size); + if (!AdapterInfo) + { + ApiLock(); + return FALSE; + } + + if (GetAdaptersInfo(AdapterInfo, &Size) != NO_ERROR) + { + ApiLock(); + return FALSE; + } + + Orig = AdapterInfo; + for (; AdapterInfo != NULL; AdapterInfo = AdapterInfo->Next) + { + if (AdapterInfo->Index == IfEntry->dwIndex) + break; + } + + if (AdapterInfo == NULL) + { + HeapFree(GetProcessHeap(), 0, Orig); + ApiLock(); + return FALSE; + } + } + else if (Ret != NO_ERROR) + { + HeapFree(GetProcessHeap(), 0, Orig); + ApiLock(); + return FALSE; + } + + if (!strcmp(AdapterInfo->IpAddressList.IpAddress.String, ZeroAddress)) + { + HeapFree(GetProcessHeap(), 0, Orig); + ApiLock(); + return TRUE; + } + else + { + HeapFree(GetProcessHeap(), 0, Orig); + ApiLock(); + return FALSE; + } +} + /* * XXX Figure out the way to bind a specific adapter to a socket. */ @@ -241,12 +320,35 @@ DWORD WINAPI AdapterDiscoveryThread(LPVOID Context) { if ((Adapter = AdapterFindByHardwareAddress(Table->table[i].bPhysAddr, Table->table[i].dwPhysAddrLen))) { + proto = find_protocol_by_adapter(&Adapter->DhclientInfo); + /* This is an existing adapter */ if (InterfaceConnected(&Table->table[i])) { /* We're still active so we stay in the list */ ifi = &Adapter->DhclientInfo; + + /* This is a hack because IP helper API sucks */ + if (IsReconnectHackNeeded(Adapter, &Table->table[i])) + { + /* This handles a disconnect/reconnect */ + + if (proto) + remove_protocol(proto); + Adapter->DhclientInfo.client->state = S_INIT; + + /* These are already invalid since the media state change */ + Adapter->RouterMib.dwForwardNextHop = 0; + Adapter->NteContext = 0; + + add_protocol(Adapter->DhclientInfo.name, + Adapter->DhclientInfo.rfdesc, + got_one, &Adapter->DhclientInfo); + state_init(&Adapter->DhclientInfo); + + SetEvent(AdapterStateChangedEvent); + } + } else { - proto = find_protocol_by_adapter(&Adapter->DhclientInfo); if (proto) remove_protocol(proto); diff --git a/reactos/dll/win32/dhcpcsvc/dhcp/api.c b/reactos/dll/win32/dhcpcsvc/dhcp/api.c index 26723f9c38e..2a9ba0fd5e3 100644 --- a/reactos/dll/win32/dhcpcsvc/dhcp/api.c +++ b/reactos/dll/win32/dhcpcsvc/dhcp/api.c @@ -101,9 +101,15 @@ DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { if( Adapter ) { if (Adapter->NteContext) + { DeleteIPAddress( Adapter->NteContext ); + Adapter->NteContext = 0; + } if (Adapter->RouterMib.dwForwardNextHop) + { DeleteIpForwardEntry( &Adapter->RouterMib ); + Adapter->RouterMib.dwForwardNextHop = 0; + } proto = find_protocol_by_adapter( &Adapter->DhclientInfo ); if (proto) @@ -171,9 +177,15 @@ DWORD DSStaticRefreshParams( PipeSendFunc Send, COMM_DHCP_REQ *Req ) { if( Adapter ) { if (Adapter->NteContext) + { DeleteIPAddress( Adapter->NteContext ); + Adapter->NteContext = 0; + } if (Adapter->RouterMib.dwForwardNextHop) + { DeleteIpForwardEntry( &Adapter->RouterMib ); + Adapter->RouterMib.dwForwardNextHop = 0; + } Adapter->DhclientState.state = S_STATIC; proto = find_protocol_by_adapter( &Adapter->DhclientInfo ); diff --git a/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c b/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c index cbdb4fef4c9..b8a49f4ccdd 100644 --- a/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c +++ b/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c @@ -548,7 +548,10 @@ void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) { if( Adapter->NteContext ) + { DeleteIPAddress( Adapter->NteContext ); + Adapter->NteContext = 0; + } /* Set up our default router if we got one from the DHCP server */ if( new_lease->options[DHO_SUBNET_MASK].len ) { @@ -1007,7 +1010,7 @@ send_discover(void *ipp) we haven't found anything for this interface yet. */ if (interval > ip->client->config->timeout) { state_panic(ip); - return; + ip->client->first_sending = cur_time; } /* If we're selecting media, try the whole list before doing @@ -1100,17 +1103,9 @@ state_panic(void *ipp) { struct interface_info *ip = ipp; PDHCP_ADAPTER Adapter = AdapterFindInfo(ip); - time_t cur_time; - - time(&cur_time); note("No DHCPOFFERS received."); - note("No working leases in persistent database - sleeping.\n"); - ip->client->state = S_INIT; - add_timeout(cur_time + ip->client->config->retry_interval, state_init, - ip); - if (!Adapter->NteContext) { /* Generate an automatic private address */ @@ -1181,7 +1176,10 @@ send_request(void *ipp) discover a new address. */ if( Adapter ) + { DeleteIPAddress( Adapter->NteContext ); + Adapter->NteContext = 0; + } ip->client->state = S_INIT; state_init(ip); diff --git a/reactos/dll/win32/iphlpapi/iphlpapi_main.c b/reactos/dll/win32/iphlpapi/iphlpapi_main.c index 6b4791efd8f..d03bcee7471 100644 --- a/reactos/dll/win32/iphlpapi/iphlpapi_main.c +++ b/reactos/dll/win32/iphlpapi/iphlpapi_main.c @@ -639,6 +639,7 @@ DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) ptr->IpAddressList.IpAddress.String); toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]), ptr->IpAddressList.IpMask.String); + ptr->IpAddressList.Context = ptr->Index; toIPAddressString(getInterfaceGatewayByIndex(table->indexes[ndx]), ptr->GatewayList.IpAddress.String); getDhcpInfoForAdapter(table->indexes[ndx], &dhcpEnabled, @@ -1189,7 +1190,7 @@ DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSi pIpForwardTable->dwNumEntries = table->numRoutes; for (ndx = 0; ndx < numRoutes; ndx++) { pIpForwardTable->table[ndx].dwForwardIfIndex = - table->routes[ndx].ifIndex + 1; + table->routes[ndx].ifIndex; pIpForwardTable->table[ndx].dwForwardDest = table->routes[ndx].dest; pIpForwardTable->table[ndx].dwForwardMask = diff --git a/reactos/dll/win32/netcfgx/tcpipconf_notify.c b/reactos/dll/win32/netcfgx/tcpipconf_notify.c index a71d0de9181..cb521e8607e 100644 --- a/reactos/dll/win32/netcfgx/tcpipconf_notify.c +++ b/reactos/dll/win32/netcfgx/tcpipconf_notify.c @@ -3230,27 +3230,25 @@ INetCfgComponentControl_fnApplyRegistryChanges( } } - if (pOldConfig->Gw) + dwSize = 0; + if (GetIpForwardTable(NULL, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) { - dwSize = 0; - if (GetIpForwardTable(NULL, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) + DWORD Index; + PMIB_IPFORWARDTABLE pIpForwardTable = (PMIB_IPFORWARDTABLE)CoTaskMemAlloc(dwSize); + if (pIpForwardTable) { - DWORD Index; - PMIB_IPFORWARDTABLE pIpForwardTable = (PMIB_IPFORWARDTABLE)CoTaskMemAlloc(dwSize); - if (pIpForwardTable) + if (GetIpForwardTable(pIpForwardTable, &dwSize, FALSE) == NO_ERROR) { - if (GetIpForwardTable(pIpForwardTable, &dwSize, FALSE) == NO_ERROR) + for (Index = 0; Index < pIpForwardTable->dwNumEntries; Index++) { - for (Index = 0; Index < pIpForwardTable->dwNumEntries; Index++) + if (pIpForwardTable->table[Index].dwForwardIfIndex == pOldConfig->Index && + pIpForwardTable->table[Index].dwForwardDest == 0) { - if (pIpForwardTable->table[Index].dwForwardIfIndex == pOldConfig->Index) - { - DeleteIpForwardEntry(&pIpForwardTable->table[Index]); - } + DeleteIpForwardEntry(&pIpForwardTable->table[Index]); } } - CoTaskMemFree(pIpForwardTable); } + CoTaskMemFree(pIpForwardTable); } } diff --git a/reactos/drivers/network/tcpip/datalink/lan.c b/reactos/drivers/network/tcpip/datalink/lan.c index 955fbe3ca7b..452f716c8ba 100644 --- a/reactos/drivers/network/tcpip/datalink/lan.c +++ b/reactos/drivers/network/tcpip/datalink/lan.c @@ -24,6 +24,11 @@ typedef struct _LAN_WQ_ITEM { BOOLEAN LegacyReceive; } LAN_WQ_ITEM, *PLAN_WQ_ITEM; +typedef struct _RECONFIGURE_CONTEXT { + ULONG State; + PLAN_ADAPTER Adapter; +} RECONFIGURE_CONTEXT, *PRECONFIGURE_CONTEXT; + NDIS_HANDLE NdisProtocolHandle = (NDIS_HANDLE)NULL; BOOLEAN ProtocolRegistered = FALSE; LIST_ENTRY AdapterListHead; @@ -555,6 +560,237 @@ VOID NTAPI ProtocolReceiveComplete( TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); } +BOOLEAN ReadIpConfiguration(PIP_INTERFACE Interface) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE ParameterHandle; + PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; + WCHAR Buffer[150]; + UNICODE_STRING IPAddress = RTL_CONSTANT_STRING(L"IPAddress"); + UNICODE_STRING Netmask = RTL_CONSTANT_STRING(L"SubnetMask"); + UNICODE_STRING Gateway = RTL_CONSTANT_STRING(L"DefaultGateway"); + UNICODE_STRING EnableDhcp = RTL_CONSTANT_STRING(L"EnableDHCP"); + UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"); + UNICODE_STRING TcpipRegistryPath; + UNICODE_STRING RegistryDataU; + ANSI_STRING RegistryDataA; + ULONG Unused; + NTSTATUS Status; + IP_ADDRESS DefaultMask, Router; + + AddrInitIPv4(&DefaultMask, 0); + + TcpipRegistryPath.MaximumLength = sizeof(WCHAR) * 150; + TcpipRegistryPath.Length = 0; + TcpipRegistryPath.Buffer = Buffer; + + /* Build the registry path */ + RtlAppendUnicodeStringToString(&TcpipRegistryPath, &Prefix); + RtlAppendUnicodeStringToString(&TcpipRegistryPath, &Interface->Name); + + InitializeObjectAttributes(&ObjectAttributes, + &TcpipRegistryPath, + OBJ_CASE_INSENSITIVE, + 0, + NULL); + + /* Open a handle to the adapter parameters */ + Status = ZwOpenKey(&ParameterHandle, KEY_READ, &ObjectAttributes); + + if (!NT_SUCCESS(Status)) + { + return FALSE; + } + else + { + KeyValueInfo = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR)); + if (!KeyValueInfo) + { + ZwClose(ParameterHandle); + return FALSE; + } + + /* Read the EnableDHCP entry */ + Status = ZwQueryValueKey(ParameterHandle, + &EnableDhcp, + KeyValuePartialInformation, + KeyValueInfo, + sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG), + &Unused); + if (NT_SUCCESS(Status) && KeyValueInfo->DataLength == sizeof(ULONG) && (*(PULONG)KeyValueInfo->Data) == 0) + { + RegistryDataU.MaximumLength = 16 + sizeof(WCHAR); + RegistryDataU.Buffer = (PWCHAR)KeyValueInfo->Data; + + /* Read the IP address */ + Status = ZwQueryValueKey(ParameterHandle, + &IPAddress, + KeyValuePartialInformation, + KeyValueInfo, + sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR), + &Unused); + if (NT_SUCCESS(Status)) + { + RegistryDataU.Length = KeyValueInfo->DataLength; + + RtlUnicodeStringToAnsiString(&RegistryDataA, + &RegistryDataU, + TRUE); + + AddrInitIPv4(&Interface->Unicast, inet_addr(RegistryDataA.Buffer)); + + RtlFreeAnsiString(&RegistryDataA); + } + + Status = ZwQueryValueKey(ParameterHandle, + &Netmask, + KeyValuePartialInformation, + KeyValueInfo, + sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR), + &Unused); + if (NT_SUCCESS(Status)) + { + RegistryDataU.Length = KeyValueInfo->DataLength; + + RtlUnicodeStringToAnsiString(&RegistryDataA, + &RegistryDataU, + TRUE); + + AddrInitIPv4(&Interface->Netmask, inet_addr(RegistryDataA.Buffer)); + + RtlFreeAnsiString(&RegistryDataA); + } + + /* We have to wait until both IP address and subnet mask + * are read to add the interface route, but we must do it + * before we add the default gateway */ + if (!AddrIsUnspecified(&Interface->Unicast) && + !AddrIsUnspecified(&Interface->Netmask)) + IPAddInterfaceRoute(Interface); + + /* Read default gateway info */ + Status = ZwQueryValueKey(ParameterHandle, + &Gateway, + KeyValuePartialInformation, + KeyValueInfo, + sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR), + &Unused); + if (NT_SUCCESS(Status)) + { + RegistryDataU.Length = KeyValueInfo->DataLength; + + RtlUnicodeStringToAnsiString(&RegistryDataA, + &RegistryDataU, + TRUE); + + AddrInitIPv4(&Router, inet_addr(RegistryDataA.Buffer)); + + if (!AddrIsUnspecified(&Router)) + RouterCreateRoute(&DefaultMask, &DefaultMask, &Router, Interface, 1); + + RtlFreeAnsiString(&RegistryDataA); + } + } + + ZwClose(ParameterHandle); + } + + return TRUE; +} + +BOOLEAN ReconfigureAdapter(PRECONFIGURE_CONTEXT Context) +{ + PLAN_ADAPTER Adapter = Context->Adapter; + PIP_INTERFACE Interface = Adapter->Context; + //NDIS_STATUS NdisStatus; + IP_ADDRESS DefaultMask; + + /* Initalize the default unspecified address (0.0.0.0) */ + AddrInitIPv4(&DefaultMask, 0); + if (Context->State == LAN_STATE_STARTED && + !Context->Adapter->CompletingReset) + { + /* Read the IP configuration */ + ReadIpConfiguration(Interface); + + /* Compute the broadcast address */ + Interface->Broadcast.Type = IP_ADDRESS_V4; + Interface->Broadcast.Address.IPv4Address = Interface->Unicast.Address.IPv4Address | + ~Interface->Netmask.Address.IPv4Address; + } + else if (!Context->Adapter->CompletingReset) + { + /* Clear IP configuration */ + Interface->Unicast = DefaultMask; + Interface->Netmask = DefaultMask; + Interface->Broadcast = DefaultMask; + + /* Remove all interface routes */ + RouterRemoveRoutesForInterface(Interface); + + /* Destroy all cached neighbors */ + NBDestroyNeighborsForInterface(Interface); + } + + Context->Adapter->CompletingReset = FALSE; + + /* We're done here if the adapter isn't connected */ + if (Context->State != LAN_STATE_STARTED) + { + Adapter->State = Context->State; + return TRUE; + } + + /* NDIS Bug! */ +#if 0 + /* Get maximum link speed */ + NdisStatus = NDISCall(Adapter, + NdisRequestQueryInformation, + OID_GEN_LINK_SPEED, + &Interface->Speed, + sizeof(UINT)); + + if (!NT_SUCCESS(NdisStatus)) + Interface->Speed = IP_DEFAULT_LINK_SPEED; + + Adapter->Speed = Interface->Speed * 100L; + + /* Get maximum frame size */ + NdisStatus = NDISCall(Adapter, + NdisRequestQueryInformation, + OID_GEN_MAXIMUM_FRAME_SIZE, + &Adapter->MTU, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) + return FALSE; + + Interface->MTU = Adapter->MTU; + + /* Get maximum packet size */ + NdisStatus = NDISCall(Adapter, + NdisRequestQueryInformation, + OID_GEN_MAXIMUM_TOTAL_SIZE, + &Adapter->MaxPacketSize, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) + return FALSE; +#endif + + Adapter->State = Context->State; + + return TRUE; +} + +VOID ReconfigureAdapterWorker(PVOID Context) +{ + PRECONFIGURE_CONTEXT ReconfigureContext = Context; + + /* Complete the reconfiguration asynchronously */ + ReconfigureAdapter(ReconfigureContext); + + /* Free the context */ + ExFreePool(ReconfigureContext); +} VOID NTAPI ProtocolStatus( NDIS_HANDLE BindingContext, @@ -571,31 +807,73 @@ VOID NTAPI ProtocolStatus( */ { PLAN_ADAPTER Adapter = BindingContext; + PRECONFIGURE_CONTEXT Context; TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + Context = ExAllocatePool(NonPagedPool, sizeof(RECONFIGURE_CONTEXT)); + if (!Context) + return; + + Context->Adapter = Adapter; switch(GeneralStatus) { - case NDIS_STATUS_MEDIA_CONNECT: - DbgPrint("NDIS_STATUS_MEDIA_CONNECT\n"); - break; + case NDIS_STATUS_MEDIA_CONNECT: + DbgPrint("NDIS_STATUS_MEDIA_CONNECT\n"); - case NDIS_STATUS_MEDIA_DISCONNECT: - DbgPrint("NDIS_STATUS_MEDIA_DISCONNECT\n"); - break; + if (Adapter->State == LAN_STATE_STARTED) + { + ExFreePool(Context); + return; + } - case NDIS_STATUS_RESET_START: - Adapter->State = LAN_STATE_RESETTING; - break; + Context->State = LAN_STATE_STARTED; + break; + + case NDIS_STATUS_MEDIA_DISCONNECT: + DbgPrint("NDIS_STATUS_MEDIA_DISCONNECT\n"); + + if (Adapter->State == LAN_STATE_STOPPED) + { + ExFreePool(Context); + return; + } + + Context->State = LAN_STATE_STOPPED; + break; - case NDIS_STATUS_RESET_END: - Adapter->State = LAN_STATE_STARTED; - break; + case NDIS_STATUS_RESET_START: + Adapter->OldState = Adapter->State; + Adapter->State = LAN_STATE_RESETTING; + /* Nothing else to do here */ + ExFreePool(Context); + return; - default: - DbgPrint("Unhandled status: %x", GeneralStatus); - break; + case NDIS_STATUS_RESET_END: + Adapter->CompletingReset = TRUE; + Context->State = Adapter->OldState; + break; + + default: + DbgPrint("Unhandled status: %x", GeneralStatus); + ExFreePool(Context); + return; } + + /* Queue the work item */ + if (!ChewCreate(ReconfigureAdapterWorker, Context)) + ExFreePool(Context); +} + +VOID NTAPI ProtocolStatusComplete(NDIS_HANDLE NdisBindingContext) +/* + * FUNCTION: Called by NDIS when a status-change has occurred + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + */ +{ + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); } NDIS_STATUS NTAPI @@ -627,17 +905,6 @@ ProtocolPnPEvent( } } -VOID NTAPI ProtocolStatusComplete( - NDIS_HANDLE NdisBindingContext) -/* - * FUNCTION: Called by NDIS when a status-change has occurred - * ARGUMENTS: - * BindingContext = Pointer to a device context (LAN_ADAPTER) - */ -{ - TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); -} - VOID NTAPI ProtocolBindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindContext, @@ -1033,21 +1300,8 @@ BOOLEAN BindAdapter( PIP_INTERFACE IF; NDIS_STATUS NdisStatus; LLIP_BIND_INFO BindInfo; - IP_ADDRESS DefaultMask, Router; - ULONG Lookahead = LOOKAHEAD_SIZE, Unused; + ULONG Lookahead = LOOKAHEAD_SIZE; NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE ParameterHandle; - PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; - WCHAR Buffer[150]; - UNICODE_STRING IPAddress = RTL_CONSTANT_STRING(L"IPAddress"); - UNICODE_STRING Netmask = RTL_CONSTANT_STRING(L"SubnetMask"); - UNICODE_STRING Gateway = RTL_CONSTANT_STRING(L"DefaultGateway"); - UNICODE_STRING EnableDhcp = RTL_CONSTANT_STRING(L"EnableDHCP"); - UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"); - UNICODE_STRING TcpipRegistryPath; - UNICODE_STRING RegistryDataU; - ANSI_STRING RegistryDataA; TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); @@ -1067,7 +1321,6 @@ BOOLEAN BindAdapter( BindInfo.Context = Adapter; BindInfo.HeaderSize = Adapter->HeaderSize; BindInfo.MinFrameSize = Adapter->MinFrameSize; - BindInfo.MTU = Adapter->MTU; BindInfo.Address = (PUCHAR)&Adapter->HWAddress; BindInfo.AddressLength = Adapter->HWAddressLength; BindInfo.Transmit = LANTransmit; @@ -1100,149 +1353,44 @@ BOOLEAN BindAdapter( TI_DbgPrint(DEBUG_DATALINK,("Adapter Description: %wZ\n", &IF->Description)); - TcpipRegistryPath.MaximumLength = sizeof(WCHAR) * 150; - TcpipRegistryPath.Length = 0; - TcpipRegistryPath.Buffer = Buffer; - - RtlAppendUnicodeStringToString(&TcpipRegistryPath, - &Prefix); - - RtlAppendUnicodeStringToString(&TcpipRegistryPath, - &IF->Name); - - InitializeObjectAttributes(&ObjectAttributes, - &TcpipRegistryPath, - OBJ_CASE_INSENSITIVE, - 0, - NULL); - - AddrInitIPv4(&DefaultMask, 0); - - Status = ZwOpenKey(&ParameterHandle, KEY_READ, &ObjectAttributes); - - if (!NT_SUCCESS(Status)) - { - IF->Unicast = DefaultMask; - IF->Netmask = DefaultMask; - } - else - { - KeyValueInfo = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR)); - if (!KeyValueInfo) - { - ZwClose(ParameterHandle); - IPDestroyInterface(IF); - return FALSE; - } - - Status = ZwQueryValueKey(ParameterHandle, - &EnableDhcp, - KeyValuePartialInformation, - KeyValueInfo, - sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG), - &Unused); - if (NT_SUCCESS(Status) && KeyValueInfo->DataLength == sizeof(ULONG) && (*(PULONG)KeyValueInfo->Data) == 0) - { - RegistryDataU.MaximumLength = 16 + sizeof(WCHAR); - RegistryDataU.Buffer = (PWCHAR)KeyValueInfo->Data; - - Status = ZwQueryValueKey(ParameterHandle, - &IPAddress, - KeyValuePartialInformation, - KeyValueInfo, - sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR), - &Unused); - if (NT_SUCCESS(Status)) - { - RegistryDataU.Length = KeyValueInfo->DataLength; - - RtlUnicodeStringToAnsiString(&RegistryDataA, - &RegistryDataU, - TRUE); - - AddrInitIPv4(&IF->Unicast, inet_addr(RegistryDataA.Buffer)); - - RtlFreeAnsiString(&RegistryDataA); - - } - else - { - IF->Unicast = DefaultMask; - } - - Status = ZwQueryValueKey(ParameterHandle, - &Netmask, - KeyValuePartialInformation, - KeyValueInfo, - sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR), - &Unused); - if (NT_SUCCESS(Status)) - { - RegistryDataU.Length = KeyValueInfo->DataLength; - - RtlUnicodeStringToAnsiString(&RegistryDataA, - &RegistryDataU, - TRUE); - - AddrInitIPv4(&IF->Netmask, inet_addr(RegistryDataA.Buffer)); - - RtlFreeAnsiString(&RegistryDataA); - } - else - { - IF->Netmask = DefaultMask; - } - - Status = ZwQueryValueKey(ParameterHandle, - &Gateway, - KeyValuePartialInformation, - KeyValueInfo, - sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR), - &Unused); - if (NT_SUCCESS(Status)) - { - RegistryDataU.Length = KeyValueInfo->DataLength; - - RtlUnicodeStringToAnsiString(&RegistryDataA, - &RegistryDataU, - TRUE); - - AddrInitIPv4(&Router, inet_addr(RegistryDataA.Buffer)); - - RtlFreeAnsiString(&RegistryDataA); - - if (!AddrIsUnspecified(&Router)) RouterCreateRoute(&DefaultMask, &DefaultMask, &Router, IF, 1); - } - } - else - { - IF->Unicast = DefaultMask; - IF->Netmask = DefaultMask; - } - - ZwClose(ParameterHandle); - } - - IF->Broadcast.Type = IP_ADDRESS_V4; - IF->Broadcast.Address.IPv4Address = - IF->Unicast.Address.IPv4Address | - ~IF->Netmask.Address.IPv4Address; - - TI_DbgPrint(DEBUG_DATALINK,("BCAST(IF) %s\n", A2S(&IF->Broadcast))); - /* Get maximum link speed */ NdisStatus = NDISCall(Adapter, NdisRequestQueryInformation, OID_GEN_LINK_SPEED, &IF->Speed, sizeof(UINT)); - - if( !NT_SUCCESS(NdisStatus) ) - IF->Speed = IP_DEFAULT_LINK_SPEED; - + + if (!NT_SUCCESS(NdisStatus)) + IF->Speed = IP_DEFAULT_LINK_SPEED; + + Adapter->Speed = IF->Speed * 100L; + + /* Get maximum frame size */ + NdisStatus = NDISCall(Adapter, + NdisRequestQueryInformation, + OID_GEN_MAXIMUM_FRAME_SIZE, + &Adapter->MTU, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) + return FALSE; + + IF->MTU = Adapter->MTU; + + /* Get maximum packet size */ + NdisStatus = NDISCall(Adapter, + NdisRequestQueryInformation, + OID_GEN_MAXIMUM_TOTAL_SIZE, + &Adapter->MaxPacketSize, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) + return FALSE; + /* Register interface with IP layer */ IPRegisterInterface(IF); + /* Set adapter state */ + Adapter->Context = IF; + /* Set packet filter so we can send and receive packets */ NdisStatus = NDISCall(Adapter, NdisRequestSetInformation, @@ -1256,9 +1404,10 @@ BOOLEAN BindAdapter( IPDestroyInterface(IF); return FALSE; } + + /* Indicate media connect (our drivers are broken and don't do this) */ + ProtocolStatus(Adapter, NDIS_STATUS_MEDIA_CONNECT, NULL, 0); - Adapter->Context = IF; - Adapter->State = LAN_STATE_STARTED; return TRUE; } @@ -1301,7 +1450,6 @@ NDIS_STATUS LANRegisterAdapter( UINT MediaIndex; NDIS_MEDIUM MediaArray[MAX_MEDIA]; UINT AddressOID; - UINT Speed; TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); @@ -1372,30 +1520,6 @@ NDIS_STATUS LANRegisterAdapter( return NDIS_STATUS_NOT_SUPPORTED; } - /* Get maximum frame size */ - NdisStatus = NDISCall(IF, - NdisRequestQueryInformation, - OID_GEN_MAXIMUM_FRAME_SIZE, - &IF->MTU, - sizeof(UINT)); - if (NdisStatus != NDIS_STATUS_SUCCESS) { - TI_DbgPrint(DEBUG_DATALINK,("denying adapter %wZ (NDISCall)\n", AdapterName)); - ExFreePoolWithTag(IF, LAN_ADAPTER_TAG); - return NdisStatus; - } - - /* Get maximum packet size */ - NdisStatus = NDISCall(IF, - NdisRequestQueryInformation, - OID_GEN_MAXIMUM_TOTAL_SIZE, - &IF->MaxPacketSize, - sizeof(UINT)); - if (NdisStatus != NDIS_STATUS_SUCCESS) { - TI_DbgPrint(MIN_TRACE, ("Query for maximum packet size failed.\n")); - ExFreePoolWithTag(IF, LAN_ADAPTER_TAG); - return NdisStatus; - } - /* Get maximum number of packets we can pass to NdisSend(Packets) at one time */ NdisStatus = NDISCall(IF, NdisRequestQueryInformation, @@ -1419,21 +1543,6 @@ NDIS_STATUS LANRegisterAdapter( return NdisStatus; } - /* Get maximum link speed */ - NdisStatus = NDISCall(IF, - NdisRequestQueryInformation, - OID_GEN_LINK_SPEED, - &Speed, - sizeof(UINT)); - if (NdisStatus != NDIS_STATUS_SUCCESS) { - TI_DbgPrint(MIN_TRACE, ("Query for maximum link speed failed.\n")); - ExFreePoolWithTag(IF, LAN_ADAPTER_TAG); - return NdisStatus; - } - - /* Convert returned link speed to bps (it is in 100bps increments) */ - IF->Speed = Speed * 100L; - /* Bind adapter to IP layer */ if( !BindAdapter(IF, RegistryPath) ) { TI_DbgPrint(DEBUG_DATALINK,("denying adapter %wZ (BindAdapter)\n", AdapterName)); diff --git a/reactos/drivers/network/tcpip/include/ip.h b/reactos/drivers/network/tcpip/include/ip.h index b448b517c79..56e52dede59 100644 --- a/reactos/drivers/network/tcpip/include/ip.h +++ b/reactos/drivers/network/tcpip/include/ip.h @@ -127,7 +127,6 @@ typedef struct _LLIP_BIND_INFO { PVOID Context; /* Pointer to link layer context information */ UINT HeaderSize; /* Size of link level header */ UINT MinFrameSize; /* Minimum frame size in bytes */ - UINT MTU; /* Maximum transmission unit */ PUCHAR Address; /* Pointer to interface address */ UINT AddressLength; /* Length of address in bytes */ LL_TRANSMIT_ROUTINE Transmit; /* Transmit function for this interface */ diff --git a/reactos/drivers/network/tcpip/include/lan.h b/reactos/drivers/network/tcpip/include/lan.h index 2792c25c6da..ab8f4bc5ba6 100644 --- a/reactos/drivers/network/tcpip/include/lan.h +++ b/reactos/drivers/network/tcpip/include/lan.h @@ -39,7 +39,8 @@ typedef struct ETH_HEADER { typedef struct LAN_ADAPTER { LIST_ENTRY ListEntry; /* Entry on list */ KSPIN_LOCK Lock; /* Lock for this structure */ - UCHAR State; /* State of the adapter */ + UCHAR State, OldState; /* State of the adapter */ + BOOLEAN CompletingReset; /* Reset is finishing */ KEVENT Event; /* Opening event */ PVOID Context; /* Upper layer context information */ NDIS_HANDLE NdisHandle; /* NDIS binding handle */ diff --git a/reactos/drivers/network/tcpip/include/neighbor.h b/reactos/drivers/network/tcpip/include/neighbor.h index 9933a133eff..4bc4c269dcb 100644 --- a/reactos/drivers/network/tcpip/include/neighbor.h +++ b/reactos/drivers/network/tcpip/include/neighbor.h @@ -43,16 +43,16 @@ typedef struct NEIGHBOR_CACHE_ENTRY { #define NUD_STALE 0x04 /* Timeout for incomplete NCE ARP requests */ -#define ARP_INCOMPLETE_TIMEOUT 5 +#define ARP_INCOMPLETE_TIMEOUT 3 /* Number of seconds between ARP transmissions */ #define ARP_RATE 900 /* Number of seconds before the NCE times out */ -#define ARP_COMPLETE_TIMEOUT (ARP_RATE + 15) +#define ARP_COMPLETE_TIMEOUT (ARP_RATE + 9) /* Number of seconds before retransmission */ -#define ARP_TIMEOUT_RETRANSMISSION 5 +#define ARP_TIMEOUT_RETRANSMISSION 3 extern NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1]; @@ -87,7 +87,8 @@ PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor( PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor( PIP_INTERFACE Interface, - PIP_ADDRESS Address); + PIP_ADDRESS Address, + BOOLEAN NoTimeout); BOOLEAN NBQueuePacket( PNEIGHBOR_CACHE_ENTRY NCE, @@ -105,4 +106,6 @@ ULONG NBCopyNeighbors( VOID NBResetNeighborTimeout( PIP_ADDRESS Address); +VOID NBDestroyNeighborsForInterface(PIP_INTERFACE Interface); + /* EOF */ diff --git a/reactos/drivers/network/tcpip/include/router.h b/reactos/drivers/network/tcpip/include/router.h index 6b2b2bb5010..6c4f49ab94c 100644 --- a/reactos/drivers/network/tcpip/include/router.h +++ b/reactos/drivers/network/tcpip/include/router.h @@ -43,6 +43,8 @@ NTSTATUS RouterStartup( NTSTATUS RouterShutdown( VOID); +VOID RouterRemoveRoutesForInterface(PIP_INTERFACE Interface); + UINT CountFIBs(PIP_INTERFACE IF); UINT CopyFIBs( PIP_INTERFACE IF, PFIB_ENTRY Target ); diff --git a/reactos/drivers/network/tcpip/tcpip/dispatch.c b/reactos/drivers/network/tcpip/tcpip/dispatch.c index aa0a0835fd2..316fe4b6a6e 100644 --- a/reactos/drivers/network/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/network/tcpip/tcpip/dispatch.c @@ -1552,8 +1552,10 @@ NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { IF->Unicast.Type = IP_ADDRESS_V4; IF->Unicast.Address.IPv4Address = IpAddrChange->Address; + IF->Netmask.Type = IP_ADDRESS_V4; IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask; + IF->Broadcast.Type = IP_ADDRESS_V4; IF->Broadcast.Address.IPv4Address = IF->Unicast.Address.IPv4Address | @@ -1587,10 +1589,13 @@ NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) { IPRemoveInterfaceRoute( IF ); IF->Unicast.Type = IP_ADDRESS_V4; IF->Unicast.Address.IPv4Address = 0; + IF->Netmask.Type = IP_ADDRESS_V4; IF->Netmask.Address.IPv4Address = 0; + IF->Broadcast.Type = IP_ADDRESS_V4; IF->Broadcast.Address.IPv4Address = 0; + Status = STATUS_SUCCESS; } } EndFor(IF); diff --git a/reactos/lib/drivers/ip/network/ip.c b/reactos/lib/drivers/ip/network/ip.c index 79ccacff26c..a422bb6dd77 100644 --- a/reactos/lib/drivers/ip/network/ip.c +++ b/reactos/lib/drivers/ip/network/ip.c @@ -206,7 +206,6 @@ PIP_INTERFACE IPCreateInterface( IF->Context = BindInfo->Context; IF->HeaderSize = BindInfo->HeaderSize; IF->MinFrameSize = BindInfo->MinFrameSize; - IF->MTU = BindInfo->MTU; IF->Address = BindInfo->Address; IF->AddressLength = BindInfo->AddressLength; IF->Transmit = BindInfo->Transmit; @@ -314,11 +313,6 @@ BOOLEAN IPRegisterInterface( IF->Index = ChosenIndex; - if (!AddrIsUnspecified(&IF->Unicast)) - { - IPAddInterfaceRoute(IF); - } - /* Add interface to the global interface list */ TcpipInterlockedInsertTailList(&InterfaceListHead, &IF->ListEntry, diff --git a/reactos/lib/drivers/ip/network/loopback.c b/reactos/lib/drivers/ip/network/loopback.c index 0bf62fd509d..e44cc69d3d7 100644 --- a/reactos/lib/drivers/ip/network/loopback.c +++ b/reactos/lib/drivers/ip/network/loopback.c @@ -106,13 +106,14 @@ NDIS_STATUS LoopRegisterAdapter( BindInfo.Context = NULL; BindInfo.HeaderSize = 0; BindInfo.MinFrameSize = 0; - BindInfo.MTU = 16384; BindInfo.Address = NULL; BindInfo.AddressLength = 0; BindInfo.Transmit = LoopTransmit; Loopback = IPCreateInterface(&BindInfo); if (!Loopback) return NDIS_STATUS_RESOURCES; + + Loopback->MTU = 16384; Loopback->Name.Buffer = L"Loopback"; Loopback->Name.MaximumLength = Loopback->Name.Length = @@ -123,6 +124,8 @@ NDIS_STATUS LoopRegisterAdapter( AddrInitIPv4(&Loopback->Broadcast, LOOPBACK_BCASTADDR_IPv4); IPRegisterInterface(Loopback); + + IPAddInterfaceRoute(Loopback); TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); diff --git a/reactos/lib/drivers/ip/network/neighbor.c b/reactos/lib/drivers/ip/network/neighbor.c index 8ab72a67d55..b4e33227537 100644 --- a/reactos/lib/drivers/ip/network/neighbor.c +++ b/reactos/lib/drivers/ip/network/neighbor.c @@ -106,17 +106,27 @@ VOID NBTimeout(VOID) for (PrevNCE = &NeighborCache[i].Cache; (NCE = *PrevNCE) != NULL;) { + if (NCE->State & NUD_INCOMPLETE) + { + /* Solicit for an address */ + NBSendSolicit(NCE); + if (NCE->EventTimer == 0) + { + NCE->EventCount++; + if (NCE->EventCount == ARP_INCOMPLETE_TIMEOUT) + { + NBFlushPacketQueue(NCE, NDIS_STATUS_NETWORK_UNREACHABLE); + NCE->EventCount = 0; + } + } + } + /* Check if event timer is running */ if (NCE->EventTimer > 0) { ASSERT(!(NCE->State & NUD_PERMANENT)); NCE->EventCount++; - if (NCE->State & NUD_INCOMPLETE) - { - /* We desperately need an address in this state or - * we timeout in 5 seconds */ - NBSendSolicit(NCE); - } - else if ((NCE->EventCount > ARP_RATE && + + if ((NCE->EventCount > ARP_RATE && NCE->EventCount % ARP_TIMEOUT_RETRANSMISSION == 0) || (NCE->EventCount == ARP_RATE)) { @@ -129,7 +139,7 @@ VOID NBTimeout(VOID) if (NCE->EventTimer - NCE->EventCount == 0) { /* Unlink and destroy the NCE */ *PrevNCE = NCE->Next; - + /* Choose the proper failure status */ if (NCE->State & NUD_INCOMPLETE) { @@ -141,8 +151,9 @@ VOID NBTimeout(VOID) /* This guy was stale for way too long */ Status = NDIS_STATUS_REQUEST_ABORTED; } - + NBFlushPacketQueue(NCE, Status); + ExFreePoolWithTag(NCE, NCE_TAG); continue; @@ -223,6 +234,42 @@ VOID NBSendSolicit(PNEIGHBOR_CACHE_ENTRY NCE) NCE->Interface); } +VOID NBDestroyNeighborsForInterface(PIP_INTERFACE Interface) +{ + KIRQL OldIrql; + PNEIGHBOR_CACHE_ENTRY *PrevNCE; + PNEIGHBOR_CACHE_ENTRY NCE; + ULONG i; + + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + for (i = 0; i <= NB_HASHMASK; i++) + { + TcpipAcquireSpinLockAtDpcLevel(&NeighborCache[i].Lock); + + for (PrevNCE = &NeighborCache[i].Cache; + (NCE = *PrevNCE) != NULL;) + { + if (NCE->Interface == Interface) + { + /* Unlink and destroy the NCE */ + *PrevNCE = NCE->Next; + + NBFlushPacketQueue(NCE, NDIS_STATUS_REQUEST_ABORTED); + ExFreePoolWithTag(NCE, NCE_TAG); + + continue; + } + else + { + PrevNCE = &NCE->Next; + } + } + + TcpipReleaseSpinLockFromDpcLevel(&NeighborCache[i].Lock); + } + KeLowerIrql(OldIrql); +} + PNEIGHBOR_CACHE_ENTRY NBAddNeighbor( PIP_INTERFACE Interface, PIP_ADDRESS Address, @@ -331,7 +378,7 @@ VOID NBUpdateNeighbor( if( !(NCE->State & NUD_INCOMPLETE) ) { - NCE->EventTimer = ARP_COMPLETE_TIMEOUT; + if (NCE->EventTimer) NCE->EventTimer = ARP_COMPLETE_TIMEOUT; NBSendPackets( NCE ); } } @@ -410,7 +457,8 @@ PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor( PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor( PIP_INTERFACE Interface, - PIP_ADDRESS Address) + PIP_ADDRESS Address, + BOOLEAN NoTimeout) /* * FUNCTION: Tries to find a neighbor and if unsuccesful, creates a new NCE * ARGUMENTS: @@ -438,7 +486,7 @@ PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor( Interface->AddressLength, NUD_PERMANENT, 0); } else { NCE = NBAddNeighbor(Interface, Address, NULL, - Interface->AddressLength, NUD_INCOMPLETE, ARP_INCOMPLETE_TIMEOUT); + Interface->AddressLength, NUD_INCOMPLETE, NoTimeout ? 0 : ARP_INCOMPLETE_TIMEOUT); if (!NCE) return NULL; NBSendSolicit(NCE); } diff --git a/reactos/lib/drivers/ip/network/router.c b/reactos/lib/drivers/ip/network/router.c index 46f6795490c..09a8953ab23 100644 --- a/reactos/lib/drivers/ip/network/router.c +++ b/reactos/lib/drivers/ip/network/router.c @@ -327,7 +327,7 @@ PNEIGHBOR_CACHE_ENTRY RouteGetRouteToDestination(PIP_ADDRESS Destination) Interface = FindOnLinkInterface(Destination); if (Interface) { /* The destination address is on-link. Check our neighbor cache */ - NCE = NBFindOrCreateNeighbor(Interface, Destination); + NCE = NBFindOrCreateNeighbor(Interface, Destination, FALSE); } else { /* Destination is not on any subnets we're on. Find a router to use */ NCE = RouterGetRoute(Destination); @@ -339,6 +339,29 @@ PNEIGHBOR_CACHE_ENTRY RouteGetRouteToDestination(PIP_ADDRESS Destination) return NCE; } +VOID RouterRemoveRoutesForInterface(PIP_INTERFACE Interface) +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PFIB_ENTRY Current; + + TcpipAcquireSpinLock(&FIBLock, &OldIrql); + + CurrentEntry = FIBListHead.Flink; + while (CurrentEntry != &FIBListHead) { + NextEntry = CurrentEntry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry); + + if (Interface == Current->Router->Interface) + DestroyFIBE(Current); + + CurrentEntry = NextEntry; + } + + TcpipReleaseSpinLock(&FIBLock, OldIrql); +} + NTSTATUS RouterRemoveRoute(PIP_ADDRESS Target, PIP_ADDRESS Router) /* * FUNCTION: Removes a route from the Forward Information Base (FIB) @@ -431,8 +454,10 @@ PFIB_ENTRY RouterCreateRoute( NCE = Current->Router; - if( AddrIsEqual(NetworkAddress, &Current->NetworkAddress) && - AddrIsEqual(Netmask, &Current->Netmask) ) { + if(AddrIsEqual(NetworkAddress, &Current->NetworkAddress) && + AddrIsEqual(Netmask, &Current->Netmask) && + NCE->Interface == Interface) + { TI_DbgPrint(DEBUG_ROUTER,("Attempting to add duplicate route to %s\n", A2S(NetworkAddress))); TcpipReleaseSpinLock(&FIBLock, OldIrql); return NULL; @@ -444,7 +469,7 @@ PFIB_ENTRY RouterCreateRoute( TcpipReleaseSpinLock(&FIBLock, OldIrql); /* The NCE references RouterAddress. The NCE is referenced for us */ - NCE = NBFindOrCreateNeighbor(Interface, RouterAddress); + NCE = NBFindOrCreateNeighbor(Interface, RouterAddress, TRUE); if (!NCE) { /* Not enough free resources */