- Merge 54929, 54930, 54932, 54933, 54934, 54939, 54941, 54942, 54944, 54945, 54946...
authorCameron Gutman <aicommander@gmail.com>
Sat, 14 Jan 2012 19:42:58 +0000 (19:42 +0000)
committerCameron Gutman <aicommander@gmail.com>
Sat, 14 Jan 2012 19:42:58 +0000 (19:42 +0000)
- 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

15 files changed:
reactos/dll/win32/dhcpcsvc/dhcp/adapter.c
reactos/dll/win32/dhcpcsvc/dhcp/api.c
reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c
reactos/dll/win32/iphlpapi/iphlpapi_main.c
reactos/dll/win32/netcfgx/tcpipconf_notify.c
reactos/drivers/network/tcpip/datalink/lan.c
reactos/drivers/network/tcpip/include/ip.h
reactos/drivers/network/tcpip/include/lan.h
reactos/drivers/network/tcpip/include/neighbor.h
reactos/drivers/network/tcpip/include/router.h
reactos/drivers/network/tcpip/tcpip/dispatch.c
reactos/lib/drivers/ip/network/ip.c
reactos/lib/drivers/ip/network/loopback.c
reactos/lib/drivers/ip/network/neighbor.c
reactos/lib/drivers/ip/network/router.c

index d79b76b..2888db1 100644 (file)
@@ -200,6 +200,85 @@ InterfaceConnected(const MIB_IFROW* IfEntry)
     return 0;
 }
 
     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.
  */
 /*
  * 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)))
             {
 
             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 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 {
                 } else {
-                    proto = find_protocol_by_adapter(&Adapter->DhclientInfo);
                     if (proto)
                         remove_protocol(proto);
 
                     if (proto)
                         remove_protocol(proto);
 
index 26723f9..2a9ba0f 100644 (file)
@@ -101,9 +101,15 @@ DWORD DSReleaseIpAddressLease( PipeSendFunc Send, COMM_DHCP_REQ *Req ) {
 
     if( Adapter ) {
         if (Adapter->NteContext)
 
     if( Adapter ) {
         if (Adapter->NteContext)
+        {
             DeleteIPAddress( Adapter->NteContext );
             DeleteIPAddress( Adapter->NteContext );
+            Adapter->NteContext = 0;
+        }
         if (Adapter->RouterMib.dwForwardNextHop)
         if (Adapter->RouterMib.dwForwardNextHop)
+        {
             DeleteIpForwardEntry( &Adapter->RouterMib );
             DeleteIpForwardEntry( &Adapter->RouterMib );
+            Adapter->RouterMib.dwForwardNextHop = 0;
+        }
 
         proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
         if (proto)
 
         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)
 
     if( Adapter ) {
         if (Adapter->NteContext)
+        {
             DeleteIPAddress( Adapter->NteContext );
             DeleteIPAddress( Adapter->NteContext );
+            Adapter->NteContext = 0;
+        }
         if (Adapter->RouterMib.dwForwardNextHop)
         if (Adapter->RouterMib.dwForwardNextHop)
+        {
             DeleteIpForwardEntry( &Adapter->RouterMib );
             DeleteIpForwardEntry( &Adapter->RouterMib );
+            Adapter->RouterMib.dwForwardNextHop = 0;
+        }
         
         Adapter->DhclientState.state = S_STATIC;
         proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
         
         Adapter->DhclientState.state = S_STATIC;
         proto = find_protocol_by_adapter( &Adapter->DhclientInfo );
index cbdb4fe..b8a49f4 100644 (file)
@@ -548,7 +548,10 @@ void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
 
 
     if( Adapter->NteContext )
 
 
     if( Adapter->NteContext )
+    {
         DeleteIPAddress( 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 ) {
 
     /* 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);
           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
        }
 
        /* 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);
 {
        struct interface_info *ip = ipp;
         PDHCP_ADAPTER Adapter = AdapterFindInfo(ip);
-       time_t cur_time;
-
-       time(&cur_time);
 
        note("No DHCPOFFERS received.");
 
 
        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 */
         if (!Adapter->NteContext)
         {
             /* Generate an automatic private address */
@@ -1181,7 +1176,10 @@ send_request(void *ipp)
                discover a new address. */
 
             if( Adapter )
                discover a new address. */
 
             if( Adapter )
+            {
                 DeleteIPAddress( Adapter->NteContext );
                 DeleteIPAddress( Adapter->NteContext );
+                Adapter->NteContext = 0;
+            }
 
             ip->client->state = S_INIT;
             state_init(ip);
 
             ip->client->state = S_INIT;
             state_init(ip);
index 6b4791e..d03bcee 100644 (file)
@@ -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.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,
               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 =
           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 =
             pIpForwardTable->table[ndx].dwForwardDest =
              table->routes[ndx].dest;
             pIpForwardTable->table[ndx].dwForwardMask =
index a71d0de..cb521e8 100644 (file)
@@ -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);
                 }
             }
 
                 }
             }
 
index 955fbe3..452f716 100644 (file)
@@ -24,6 +24,11 @@ typedef struct _LAN_WQ_ITEM {
     BOOLEAN LegacyReceive;
 } LAN_WQ_ITEM, *PLAN_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;
 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"));
 }
 
     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,
 
 VOID NTAPI ProtocolStatus(
     NDIS_HANDLE BindingContext,
@@ -571,31 +807,73 @@ VOID NTAPI ProtocolStatus(
  */
 {
     PLAN_ADAPTER Adapter = BindingContext;
  */
 {
     PLAN_ADAPTER Adapter = BindingContext;
+    PRECONFIGURE_CONTEXT Context;
 
     TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
 
     TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
+    
+    Context = ExAllocatePool(NonPagedPool, sizeof(RECONFIGURE_CONTEXT));
+    if (!Context)
+        return;
+    
+    Context->Adapter = Adapter;
 
     switch(GeneralStatus)
     {
 
     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
 }
 
 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,
 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;
     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;
     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"));
 
 
     TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
 
@@ -1067,7 +1321,6 @@ BOOLEAN BindAdapter(
     BindInfo.Context       = Adapter;
     BindInfo.HeaderSize    = Adapter->HeaderSize;
     BindInfo.MinFrameSize  = Adapter->MinFrameSize;
     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;
     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));
     
     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));
     /* 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);
 
     /* 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,
     /* Set packet filter so we can send and receive packets */
     NdisStatus = NDISCall(Adapter,
                           NdisRequestSetInformation,
@@ -1256,9 +1404,10 @@ BOOLEAN BindAdapter(
         IPDestroyInterface(IF);
         return FALSE;
     }
         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;
 }
 
     return TRUE;
 }
 
@@ -1301,7 +1450,6 @@ NDIS_STATUS LANRegisterAdapter(
     UINT MediaIndex;
     NDIS_MEDIUM MediaArray[MAX_MEDIA];
     UINT AddressOID;
     UINT MediaIndex;
     NDIS_MEDIUM MediaArray[MAX_MEDIA];
     UINT AddressOID;
-    UINT Speed;
 
     TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
 
 
     TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
 
@@ -1372,30 +1520,6 @@ NDIS_STATUS LANRegisterAdapter(
         return NDIS_STATUS_NOT_SUPPORTED;
     }
 
         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,
     /* 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;
     }
 
         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));
     /* Bind adapter to IP layer */
     if( !BindAdapter(IF, RegistryPath) ) {
        TI_DbgPrint(DEBUG_DATALINK,("denying adapter %wZ (BindAdapter)\n", AdapterName));
index b448b51..56e52de 100644 (file)
@@ -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 */
     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 */
     PUCHAR Address;               /* Pointer to interface address */
     UINT  AddressLength;          /* Length of address in bytes */
     LL_TRANSMIT_ROUTINE Transmit; /* Transmit function for this interface */
index 2792c25..ab8f4bc 100644 (file)
@@ -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 */
 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 */
     KEVENT Event;                           /* Opening event */
     PVOID Context;                          /* Upper layer context information */
     NDIS_HANDLE NdisHandle;                 /* NDIS binding handle */
index 9933a13..4bc4c26 100644 (file)
@@ -43,16 +43,16 @@ typedef struct NEIGHBOR_CACHE_ENTRY {
 #define NUD_STALE      0x04
 
 /* Timeout for incomplete NCE ARP requests */
 #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 */
 
 /* 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 */
 
 /* Number of seconds before retransmission */
-#define ARP_TIMEOUT_RETRANSMISSION 5
+#define ARP_TIMEOUT_RETRANSMISSION 3
 
 extern NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1];
 
 
 extern NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1];
 
@@ -87,7 +87,8 @@ PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(
 
 PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
     PIP_INTERFACE Interface,
 
 PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
     PIP_INTERFACE Interface,
-    PIP_ADDRESS Address);
+    PIP_ADDRESS Address,
+    BOOLEAN NoTimeout);
 
 BOOLEAN NBQueuePacket(
     PNEIGHBOR_CACHE_ENTRY NCE,
 
 BOOLEAN NBQueuePacket(
     PNEIGHBOR_CACHE_ENTRY NCE,
@@ -105,4 +106,6 @@ ULONG NBCopyNeighbors(
 VOID NBResetNeighborTimeout(
     PIP_ADDRESS Address);
 
 VOID NBResetNeighborTimeout(
     PIP_ADDRESS Address);
 
+VOID NBDestroyNeighborsForInterface(PIP_INTERFACE Interface);
+
 /* EOF */
 /* EOF */
index 6b2b2bb..6c4f49a 100644 (file)
@@ -43,6 +43,8 @@ NTSTATUS RouterStartup(
 NTSTATUS RouterShutdown(
     VOID);
 
 NTSTATUS RouterShutdown(
     VOID);
 
+VOID RouterRemoveRoutesForInterface(PIP_INTERFACE Interface);
+
 UINT CountFIBs(PIP_INTERFACE IF);
 
 UINT CopyFIBs( PIP_INTERFACE IF, PFIB_ENTRY Target );
 UINT CountFIBs(PIP_INTERFACE IF);
 
 UINT CopyFIBs( PIP_INTERFACE IF, PFIB_ENTRY Target );
index aa0a083..316fe4b 100644 (file)
@@ -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->Unicast.Type = IP_ADDRESS_V4;
             IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
+
             IF->Netmask.Type = IP_ADDRESS_V4;
             IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
             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 |
             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;
             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->Netmask.Type = IP_ADDRESS_V4;
             IF->Netmask.Address.IPv4Address = 0;
+
             IF->Broadcast.Type = IP_ADDRESS_V4;
             IF->Broadcast.Address.IPv4Address = 0;
             IF->Broadcast.Type = IP_ADDRESS_V4;
             IF->Broadcast.Address.IPv4Address = 0;
+
             Status = STATUS_SUCCESS;
         }
     } EndFor(IF);
             Status = STATUS_SUCCESS;
         }
     } EndFor(IF);
index 79ccacf..a422bb6 100644 (file)
@@ -206,7 +206,6 @@ PIP_INTERFACE IPCreateInterface(
     IF->Context    = BindInfo->Context;
     IF->HeaderSize = BindInfo->HeaderSize;
     IF->MinFrameSize = BindInfo->MinFrameSize;
     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;
     IF->Address       = BindInfo->Address;
     IF->AddressLength = BindInfo->AddressLength;
     IF->Transmit      = BindInfo->Transmit;
@@ -314,11 +313,6 @@ BOOLEAN IPRegisterInterface(
 
     IF->Index = ChosenIndex;
 
 
     IF->Index = ChosenIndex;
 
-    if (!AddrIsUnspecified(&IF->Unicast))
-    {
-        IPAddInterfaceRoute(IF);
-    }
-
     /* Add interface to the global interface list */
     TcpipInterlockedInsertTailList(&InterfaceListHead,
                                   &IF->ListEntry,
     /* Add interface to the global interface list */
     TcpipInterlockedInsertTailList(&InterfaceListHead,
                                   &IF->ListEntry,
index 0bf62fd..e44cc69 100644 (file)
@@ -106,13 +106,14 @@ NDIS_STATUS LoopRegisterAdapter(
   BindInfo.Context = NULL;
   BindInfo.HeaderSize = 0;
   BindInfo.MinFrameSize = 0;
   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;
   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 =
 
   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);
   AddrInitIPv4(&Loopback->Broadcast, LOOPBACK_BCASTADDR_IPv4);
 
   IPRegisterInterface(Loopback);
+    
+  IPAddInterfaceRoute(Loopback);
 
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 
 
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 
index 8ab72a6..b4e3322 100644 (file)
@@ -106,17 +106,27 @@ VOID NBTimeout(VOID)
 
         for (PrevNCE = &NeighborCache[i].Cache;
              (NCE = *PrevNCE) != NULL;) {
 
         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++;
             /* 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))
                 {
                      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;
                 if (NCE->EventTimer - NCE->EventCount == 0) {
                     /* Unlink and destroy the NCE */
                     *PrevNCE = NCE->Next;
-
+                    
                     /* Choose the proper failure status */
                     if (NCE->State & NUD_INCOMPLETE)
                     {
                     /* 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;
                     }
                         /* This guy was stale for way too long */
                         Status = NDIS_STATUS_REQUEST_ABORTED;
                     }
-
+                    
                     NBFlushPacketQueue(NCE, Status);
                     NBFlushPacketQueue(NCE, Status);
+
                     ExFreePoolWithTag(NCE, NCE_TAG);
 
                     continue;
                     ExFreePoolWithTag(NCE, NCE_TAG);
 
                     continue;
@@ -223,6 +234,42 @@ VOID NBSendSolicit(PNEIGHBOR_CACHE_ENTRY NCE)
                 NCE->Interface);
 }
 
                 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,
 PNEIGHBOR_CACHE_ENTRY NBAddNeighbor(
   PIP_INTERFACE Interface,
   PIP_ADDRESS Address,
@@ -331,7 +378,7 @@ VOID NBUpdateNeighbor(
 
     if( !(NCE->State & NUD_INCOMPLETE) )
     {
 
     if( !(NCE->State & NUD_INCOMPLETE) )
     {
-        NCE->EventTimer = ARP_COMPLETE_TIMEOUT;
+        if (NCE->EventTimer) NCE->EventTimer = ARP_COMPLETE_TIMEOUT;
         NBSendPackets( NCE );
     }
 }
         NBSendPackets( NCE );
     }
 }
@@ -410,7 +457,8 @@ PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(
 
 PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
   PIP_INTERFACE Interface,
 
 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:
 /*
  * 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_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);
         }
             if (!NCE) return NULL;
             NBSendSolicit(NCE);
         }
index 46f6795..09a8953 100644 (file)
@@ -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 */
     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);
     } 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;
 }
 
     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)
 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;
 
 
         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;
             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 */
     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 */
 
     if (!NCE) {
         /* Not enough free resources */