diff --git a/reactos/subsys/system/dhcp/adapter.c b/reactos/subsys/system/dhcp/adapter.c index 30f30aff1a3..5b793210eb8 100644 --- a/reactos/subsys/system/dhcp/adapter.c +++ b/reactos/subsys/system/dhcp/adapter.c @@ -62,10 +62,11 @@ void AdapterInit() { DH_DbgPrint(MID_TRACE,("Got Adapter List (%d entries)\n", Table->dwNumEntries)); for( i = 0; i < Table->dwNumEntries; i++ ) { - DH_DbgPrint(MID_TRACE,("Getting adapter %d attributes\n", i)); + DH_DbgPrint(MID_TRACE,("Getting adapter %d attributes\n", + Table->table[i].dwIndex)); Adapter = calloc( sizeof( DHCP_ADAPTER ) + Table->table[i].dwMtu, 1 ); - if( Adapter ) { + if( Adapter && Table->table[i].dwType ) { memcpy( &Adapter->IfMib, &Table->table[i], sizeof(Adapter->IfMib) ); GetAddress( Adapter ); @@ -93,6 +94,7 @@ void AdapterInit() { Adapter->DhclientInfo.wfdesc = DhcpSocket; } Adapter->DhclientState.config = &Adapter->DhclientConfig; + Adapter->DhclientConfig.timeout = DHCP_PANIC_TIMEOUT; Adapter->DhclientConfig.initial_interval = DHCP_DISCOVER_INTERVAL; Adapter->DhclientConfig.retry_interval = DHCP_DISCOVER_INTERVAL; Adapter->DhclientConfig.select_interval = 1; @@ -154,6 +156,20 @@ PDHCP_ADAPTER AdapterFindName( const WCHAR *name ) { return NULL; } +PDHCP_ADAPTER AdapterFindInfo( struct interface_info *ip ) { + PDHCP_ADAPTER Adapter; + PLIST_ENTRY ListEntry; + + for( ListEntry = AdapterList.Flink; + ListEntry != &AdapterList; + ListEntry = ListEntry->Flink ) { + Adapter = CONTAINING_RECORD( ListEntry, DHCP_ADAPTER, ListEntry ); + if( ip == &Adapter->DhclientInfo ) return Adapter; + } + + return NULL; +} + PDHCP_ADAPTER AdapterGetFirst() { if( IsListEmpty( &AdapterList ) ) return NULL; else { return CONTAINING_RECORD diff --git a/reactos/subsys/system/dhcp/dhclient.c b/reactos/subsys/system/dhcp/dhclient.c index 7e42ea0d85a..4e1b3fee342 100644 --- a/reactos/subsys/system/dhcp/dhclient.c +++ b/reactos/subsys/system/dhcp/dhclient.c @@ -85,6 +85,7 @@ int privfd; struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; struct in_addr inaddr_any; struct sockaddr_in sockaddr_broadcast; +unsigned long old_default_route = 0; /* * ASSERT_STATE() does nothing now; it used to be @@ -437,20 +438,22 @@ state_selecting(void *ipp) /* Check to see if we got an ARPREPLY for the address in this particular lease. */ if (!picked) { - script_init("ARPCHECK", lp->medium); - script_write_params("check_", lp); - - /* If the ARPCHECK code detects another - machine using the offered address, it exits - nonzero. We need to send a DHCPDECLINE and - toss the lease. */ - if (script_go()) { - make_decline(ip, lp); - send_decline(ip); - goto freeit; - } - picked = lp; - picked->next = NULL; + script_init("ARPCHECK", lp->medium); + script_write_params("check_", lp); + + /* If the ARPCHECK code detects another + machine using the offered address, it exits + nonzero. We need to send a DHCPDECLINE and + toss the lease. */ +#if 0 /* XXX Later check ARP. For now, trust leases */ + if (script_go()) { + make_decline(ip, lp); + send_decline(ip); + goto freeit; + } +#endif + picked = lp; + picked->next = NULL; } else { freeit: free_client_lease(lp); @@ -580,42 +583,121 @@ dhcpack(struct packet *packet) bind_lease(ip); } +void set_name_servers( struct client_lease *new_lease ) { + if( new_lease->options[DHO_NAME_SERVERS].len ) { + HKEY RegKey; + struct iaddr nameserver; + char *nsbuf; + int i, addrs = + new_lease->options[DHO_NAME_SERVERS].len / sizeof(ULONG); + + nsbuf = malloc( addrs * sizeof(IP_ADDRESS_STRING) ); + nsbuf[0] = 0; + + if( nsbuf && !RegOpenKeyEx + ( HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + 0, KEY_WRITE, &RegKey ) ) { + for( i = 0; i < addrs; i++ ) { + memcpy( nameserver.iabuf, + new_lease->options[DHO_NAME_SERVERS].data + + (addrs * sizeof(ULONG)), sizeof(ULONG) ); + strcat( nsbuf, piaddr(nameserver) ); + if( i != addrs-1 ) strcat( nsbuf, "," ); + } + + DH_DbgPrint(MID_TRACE,("Setting Nameservers: %s\n", nsbuf)); + + RegSetValueEx( RegKey, "NameServer", 0, REG_SZ, + nsbuf, strlen(nsbuf) ); + + free( nsbuf ); + } + } +} + +void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) { + struct iaddr netmask; + + if( Adapter->NteContext ) + DeleteIPAddress( Adapter->NteContext ); + + if( new_lease->options[DHO_SUBNET_MASK].len ) { + NTSTATUS Status; + + memcpy( netmask.iabuf, + new_lease->options[DHO_SUBNET_MASK].data, + new_lease->options[DHO_SUBNET_MASK].len ); + + Status = AddIPAddress + ( *((ULONG*)new_lease->address.iabuf), + *((ULONG*)netmask.iabuf), + Adapter->IfMib.dwIndex, + &Adapter->NteContext, + &Adapter->NteInstance ); + + if( !NT_SUCCESS(Status) ) + warning("AddIPAddress: %x\n", Status); + } + + if( new_lease->options[DHO_ROUTERS].len ) { + MIB_IPFORWARDROW RouterMib; + NTSTATUS Status; + struct iaddr router; + + memcpy( netmask.iabuf, + new_lease->options[DHO_ROUTERS].data, + new_lease->options[DHO_ROUTERS].len ); + + RouterMib.dwForwardDest = 0; /* Default route */ + RouterMib.dwForwardMask = 0; + RouterMib.dwForwardMetric1 = 1; + + if( old_default_route ) { + RouterMib.dwForwardDest = old_default_route; + DeleteIpForwardEntry( &RouterMib ); + } + + RouterMib.dwForwardNextHop = *((ULONG*)router.iabuf); + + Status = CreateIpForwardEntry( &RouterMib ); + + if( !NT_SUCCESS(Status) ) + warning("CreateIpForwardEntry: %x\n", Status); + else + old_default_route = RouterMib.dwForwardNextHop; + } +} + + void bind_lease(struct interface_info *ip) { - /* Remember the medium. */ - ip->client->new->medium = ip->client->medium; + PDHCP_ADAPTER Adapter; + struct client_lease *new_lease = ip->client->new; - /* Write out the new lease. */ - write_client_lease(ip, ip->client->new, 0); + /* Remember the medium. */ + ip->client->new->medium = ip->client->medium; + ip->client->active = ip->client->new; + ip->client->new = NULL; - /* Run the client script with the new parameters. */ - script_init((ip->client->state == S_REQUESTING ? "BOUND" : - (ip->client->state == S_RENEWING ? "RENEW" : - (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))), - ip->client->new->medium); - if (ip->client->active && ip->client->state != S_REBOOTING) - script_write_params("old_", ip->client->active); - script_write_params("new_", ip->client->new); - if (ip->client->alias) - script_write_params("alias_", ip->client->alias); - script_go(); + /* Set up a timeout to start the renewal process. */ + add_timeout(ip->client->active->renewal, state_bound, ip); - /* Replace the old active lease with the new one. */ - if (ip->client->active) - free_client_lease(ip->client->active); - ip->client->active = ip->client->new; - ip->client->new = NULL; + note("bound to %s -- renewal in %d seconds.", + piaddr(ip->client->active->address), + ip->client->active->renewal - cur_time); - /* Set up a timeout to start the renewal process. */ - add_timeout(ip->client->active->renewal, state_bound, ip); + ip->client->state = S_BOUND; + + Adapter = AdapterFindInfo( ip ); - note("bound to %s -- renewal in %d seconds.", - piaddr(ip->client->active->address), - ip->client->active->renewal - cur_time); - ip->client->state = S_BOUND; - reinitialize_interfaces(); -// go_daemon(); + if( Adapter ) setup_adapter( Adapter, new_lease ); + else warning("Could not find adapter for info %p\n", ip); + + set_name_servers( new_lease ); + + reinitialize_interfaces(); } /* @@ -1588,8 +1670,6 @@ rewrite_client_leases(void) write_client_lease(ifi, ifi->client->active, 1); fflush(leaseFile); -// ftruncate(fileno(leaseFile), ftello(leaseFile)); -// fsync(fileno(leaseFile)); } void diff --git a/reactos/subsys/system/dhcp/dispatch.c b/reactos/subsys/system/dhcp/dispatch.c index 2f0435f2d0a..3fdfb2131d5 100644 --- a/reactos/subsys/system/dhcp/dispatch.c +++ b/reactos/subsys/system/dhcp/dispatch.c @@ -206,27 +206,16 @@ dispatch(void) FD_ZERO(&fds); -// fds = malloc(nfds * sizeof(struct pollfd)); -// if (fds == NULL) -// error("Can't allocate poll structures."); - do { - DH_DbgPrint(MID_TRACE,("Cycling dispatch()\n")); /* * Call any expired timeouts, and then if there's still * a timeout registered, time out the select call then. */ another: if (timeouts) { - DH_DbgPrint(MID_TRACE,("Some timeouts are available\n")); - struct timeout *t; if (timeouts->when <= cur_time) { - DH_DbgPrint(MID_TRACE,("Calling timeout %x %p %x\n", - timeouts->when, - timeouts->func, - timeouts->what)); t = timeouts; timeouts = timeouts->next; (*(t->func))(t->what); @@ -253,12 +242,7 @@ dispatch(void) struct interface_info *ip = l->local; if (ip && (l->handler != got_one || !ip->dead)) { - DH_DbgPrint(MID_TRACE,("l->fd %d\n", l->fd)); - FD_SET(l->fd, &fds); -// fds[i].fd = l->fd; -// fds[i].events = POLLIN; -// fds[i].revents = 0; i++; } } @@ -269,13 +253,26 @@ dispatch(void) /* Wait for a packet or a timeout... XXX */ timeval.tv_sec = to_msec / 1000; timeval.tv_usec = (to_msec % 1000) * 1000; - DH_DbgPrint(MID_TRACE,("select(%d,%d.%03d) =>\n", - nfds,timeval.tv_sec,timeval.tv_usec/1000)); ApiUnlock(); count = select(nfds, &fds, NULL, NULL, &timeval); - DH_DbgPrint(MID_TRACE,(" => %d\n", count)); + + DH_DbgPrint(MID_TRACE,("Select: %d\n", count)); + + /* Review poll output */ + for (i = 0, l = protocols; l; l = l->next) { + struct interface_info *ip = l->local; + + if (ip && (l->handler != got_one || !ip->dead)) { + DH_DbgPrint + (MID_TRACE, + ("set(%d) -> %s\n", + l->fd, FD_ISSET(l->fd, &fds) ? "true" : "false")); + i++; + } + } + ApiLock(); @@ -295,9 +292,7 @@ dispatch(void) for (l = protocols; l; l = l->next) { struct interface_info *ip; ip = l->local; - if (!FD_ISSET(l->fd, &fds)) { -//.revents & (POLLIN | POLLHUP))) { -// fds[i].revents = 0; + if (FD_ISSET(l->fd, &fds)) { if (ip && (l->handler != got_one || !ip->dead)) { DH_DbgPrint(MID_TRACE,("Handling %x\n", l)); @@ -309,7 +304,6 @@ dispatch(void) } interfaces_invalidated = 0; } - DH_DbgPrint(MID_TRACE,("Done\n")); } while (1); ApiUnlock(); /* Not reached currently */ diff --git a/reactos/subsys/system/dhcp/include/rosdhcp.h b/reactos/subsys/system/dhcp/include/rosdhcp.h index 44b31b7f75e..d678472b5c0 100644 --- a/reactos/subsys/system/dhcp/include/rosdhcp.h +++ b/reactos/subsys/system/dhcp/include/rosdhcp.h @@ -21,6 +21,7 @@ #undef PREFER #define DHCP_DISCOVER_INTERVAL 15 #define DHCP_REBOOT_TIMEOUT 300 +#define DHCP_PANIC_TIMEOUT DHCP_REBOOT_TIMEOUT * 3 #define DHCP_BACKOFF_MAX 300 #define _PATH_DHCLIENT_PID "\\systemroot\\system32\\drivers\\etc\\dhclient.pid" @@ -59,6 +60,7 @@ typedef DWORD (*PipeSendFunc)( COMM_DHCP_REPLY *Reply ); #define srandom srand extern PDHCP_ADAPTER AdapterFindIndex( unsigned int AdapterIndex ); +extern PDHCP_ADAPTER AdapterFindInfo( struct interface_info *info ); extern VOID ApiInit(); extern VOID ApiLock(); extern VOID ApiUnlock(); diff --git a/reactos/subsys/system/dhcp/util.c b/reactos/subsys/system/dhcp/util.c index 22d3948f920..2585ff113ab 100644 --- a/reactos/subsys/system/dhcp/util.c +++ b/reactos/subsys/system/dhcp/util.c @@ -2,8 +2,9 @@ #include "rosdhcp.h" char *piaddr( struct iaddr addr ) { - struct sockaddr_in *sa = (struct sockaddr_in *)addr.iabuf; - return inet_ntoa( sa->sin_addr ); + struct sockaddr_in sa; + memcpy(&sa.sin_addr,addr.iabuf,sizeof(sa.sin_addr)); + return inet_ntoa( sa.sin_addr ); } int note( char *format, ... ) {