[DHCPCSVC]

- Fix an issue assigning a private address after the IpReleaseAddress API was used prior to IpRenewAddress
- Move the IP refresh hack into dhcpcsvc so it now properly refresh IP information after an adapter is disconnected and reconnected (wired and wireless)
- When a state change occurs (connecting to a different wireless network or unplugging and plugging in the Ethernet cable), TCP/IP will flush routes and the neighbor cache then set the IP address to 0.0.0.0. DHCP will detect that IP address (that part is the hack since we do it via polling instead of events) then send a DHCP discover packet out via the new network connection. No more ipconfig /renew to get a new DHCP lease after network changes. It's all seamless now :D

svn path=/branches/wlan-bringup/; revision=54933
This commit is contained in:
Cameron Gutman 2012-01-13 10:03:38 +00:00
parent a8c61ab6c0
commit e8b08a9dd8
3 changed files with 120 additions and 10 deletions

View file

@ -200,6 +200,84 @@ 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 (!proto)
return FALSE;
if (Adapter->DhclientInfo.client->state != S_BOUND)
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 +319,34 @@ 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 */
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);

View file

@ -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 );

View file

@ -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);