From f9fe2ff6a872d9050bb5df437d275ddd596f3a39 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 24 Jul 2009 21:06:20 +0000 Subject: [PATCH] - Add support for adapters added after DHCP is started - Automatically request an IP address after an interface becomes ready (needed for DHCP support on WLAN adapters) svn path=/trunk/; revision=42182 --- reactos/base/services/dhcp/adapter.c | 48 +++++-- reactos/base/services/dhcp/dhclient.c | 30 ----- reactos/base/services/dhcp/dispatch.c | 126 +++---------------- reactos/base/services/dhcp/include/rosdhcp.h | 1 + 4 files changed, 56 insertions(+), 149 deletions(-) diff --git a/reactos/base/services/dhcp/adapter.c b/reactos/base/services/dhcp/adapter.c index 74cccae2d74..01225213d5e 100644 --- a/reactos/base/services/dhcp/adapter.c +++ b/reactos/base/services/dhcp/adapter.c @@ -198,6 +198,10 @@ BOOL PrepareAdapterForService( PDHCP_ADAPTER Adapter ) { (MID_TRACE,("Adapter Name: [%s] (Bind Status %x) (dynamic)\n", Adapter->DhclientInfo.name, Adapter->BindStatus)); + + add_protocol(Adapter->DhclientInfo.name, Adapter->DhclientInfo.rfdesc, got_one, &Adapter->DhclientInfo); + Adapter->DhclientInfo.client->state = S_INIT; + state_reboot(&Adapter->DhclientInfo); } if( IPAddress ) free( IPAddress ); @@ -205,21 +209,32 @@ BOOL PrepareAdapterForService( PDHCP_ADAPTER Adapter ) { return TRUE; } +void AdapterInit() { + WSAStartup(0x0101,&wsd); + + InitializeListHead( &AdapterList ); +} + +int +InterfaceConnected(MIB_IFROW IfEntry) +{ + if (IfEntry.dwOperStatus == IF_OPER_STATUS_CONNECTED || + IfEntry.dwOperStatus == IF_OPER_STATUS_OPERATIONAL) + return 1; + + return 0; +} + /* * XXX Figure out the way to bind a specific adapter to a socket. */ - -void AdapterInit() { +void AdapterDiscover() { PMIB_IFTABLE Table = (PMIB_IFTABLE) malloc(sizeof(MIB_IFTABLE)); DWORD Error, Size = sizeof(MIB_IFTABLE); PDHCP_ADAPTER Adapter = NULL; struct interface_info *ifi = NULL; int i; - WSAStartup(0x0101,&wsd); - - InitializeListHead( &AdapterList ); - DH_DbgPrint(MID_TRACE,("Getting Adapter List...\n")); while( (Error = GetIfTable(Table, &Size, 0 )) == @@ -236,9 +251,25 @@ void AdapterInit() { for( i = Table->dwNumEntries - 1; i >= 0; i-- ) { DH_DbgPrint(MID_TRACE,("Getting adapter %d attributes\n", Table->table[i].dwIndex)); + + if (AdapterFindByHardwareAddress(Table->table[i].bPhysAddr, Table->table[i].dwPhysAddrLen)) + { + /* This is an existing adapter */ + if (InterfaceConnected(Table->table[i])) { + /* We're still active so we stay in the list */ + ifi = &Adapter->DhclientInfo; + } else { + /* We've lost our link so out we go */ + RemoveEntryList(&Adapter->ListEntry); + free(Adapter); + } + + continue; + } + Adapter = (DHCP_ADAPTER*) calloc( sizeof( DHCP_ADAPTER ) + Table->table[i].dwMtu, 1 ); - if( Adapter && Table->table[i].dwType == MIB_IF_TYPE_ETHERNET ) { + if( Adapter && Table->table[i].dwType == MIB_IF_TYPE_ETHERNET && InterfaceConnected(Table->table[i])) { memcpy( &Adapter->IfMib, &Table->table[i], sizeof(Adapter->IfMib) ); Adapter->DhclientInfo.client = &Adapter->DhclientState; @@ -287,6 +318,9 @@ void AdapterInit() { if( PrepareAdapterForService( Adapter ) ) { Adapter->DhclientInfo.next = ifi; ifi = &Adapter->DhclientInfo; + + read_client_conf(&Adapter->DhclientInfo); + InsertTailList( &AdapterList, &Adapter->ListEntry ); } else { free( Adapter ); Adapter = 0; } } else { free( Adapter ); Adapter = 0; } diff --git a/reactos/base/services/dhcp/dhclient.c b/reactos/base/services/dhcp/dhclient.c index ac559a2565d..d2fc70b8204 100644 --- a/reactos/base/services/dhcp/dhclient.c +++ b/reactos/base/services/dhcp/dhclient.c @@ -129,8 +129,6 @@ static SERVICE_TABLE_ENTRY ServiceTable[2] = int main(int argc, char *argv[]) { - int i = 0; - PDHCP_ADAPTER Adapter; ApiInit(); AdapterInit(); PipeInit(); @@ -145,31 +143,6 @@ main(int argc, char *argv[]) DH_DbgPrint(MID_TRACE,("DHCP Service Started\n")); - for (Adapter = AdapterGetFirst(); - Adapter != NULL; - Adapter = AdapterGetNext(Adapter)) - { - read_client_conf(&Adapter->DhclientInfo); - - if (!interface_link_status(Adapter->DhclientInfo.name)) { - DH_DbgPrint(MID_TRACE,("%s: no link ", Adapter->DhclientInfo.name)); - Sleep(1000); - while (!interface_link_status(Adapter->DhclientInfo.name)) { - DH_DbgPrint(MID_TRACE,(".")); - if (++i > 10) { - DH_DbgPrint(MID_TRACE,("Giving up for now on adapter [%s]\n", Adapter->DhclientInfo.name)); - } - Sleep(1000); - } - DH_DbgPrint(MID_TRACE,("Got link on [%s]\n", Adapter->DhclientInfo.name)); - } - - DH_DbgPrint(MID_TRACE,("Discover Interfaces\n")); - - /* set up the interface */ - discover_interfaces(&Adapter->DhclientInfo); - } - bootp_packet_handler = do_packet; DH_DbgPrint(MID_TRACE,("Going into dispatch()\n")); @@ -611,8 +584,6 @@ bind_lease(struct interface_info *ip) else warning("Could not find adapter for info %p\n", ip); set_name_servers( Adapter, new_lease ); - - reinitialize_interfaces(); } /* @@ -1102,7 +1073,6 @@ state_panic(void *ipp) note("bound: immediate renewal."); state_bound(ip); } - reinitialize_interfaces(); return; } diff --git a/reactos/base/services/dhcp/dispatch.c b/reactos/base/services/dhcp/dispatch.c index 967e9fbf470..d408db63fe3 100644 --- a/reactos/base/services/dhcp/dispatch.c +++ b/reactos/base/services/dhcp/dispatch.c @@ -50,40 +50,10 @@ struct protocol *protocols = NULL; struct timeout *timeouts = NULL; static struct timeout *free_timeouts = NULL; -static int interfaces_invalidated = FALSE; void (*bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *); -static int interface_status(struct interface_info *ifinfo); - -/* - * Use getifaddrs() to get a list of all the attached interfaces. For - * each interface that's of type INET and not the loopback interface, - * register that interface with the network I/O software, figure out - * what subnet it's on, and add it to the list of interfaces. - */ -void -discover_interfaces(struct interface_info *iface) -{ - PDHCP_ADAPTER Adapter = AdapterFindInfo( iface ); - - if_register_receive(iface); - if_register_send(iface); - - if( Adapter->DhclientState.state != S_STATIC ) { - add_protocol(iface->name, iface->rfdesc, got_one, iface); - iface->client->state = S_INIT; - state_reboot(iface); - } -} - -void -reinitialize_interfaces(void) -{ - interfaces_invalidated = 1; -} - /* * Wait for packets to come in using poll(). When a packet comes in, * call receive_packet to receive the packet and possibly strip hardware @@ -93,7 +63,7 @@ reinitialize_interfaces(void) void dispatch(void) { - int count, i, to_msec, nfds = 0; + int count, i, to_msec, nfds; struct protocol *l; fd_set fds; time_t howlong, cur_time; @@ -101,17 +71,19 @@ dispatch(void) ApiLock(); - for (l = protocols; l; l = l->next) - nfds++; - - FD_ZERO(&fds); - do { /* * Call any expired timeouts, and then if there's still * a timeout registered, time out the select call then. */ another: + AdapterDiscover(); + + for (l = protocols, nfds = 0; l; l = l->next) + nfds++; + + FD_ZERO(&fds); + time(&cur_time); if (timeouts) { @@ -201,12 +173,9 @@ dispatch(void) !ip->dead)) { DH_DbgPrint(MID_TRACE,("Handling %x\n", l)); (*(l->handler))(l); - if (interfaces_invalidated) - break; } i++; } - interfaces_invalidated = 0; } } while (1); @@ -236,16 +205,18 @@ got_one(struct protocol *l) warning("receive_packet failed on %s: %s", ip->name, strerror(errno)); ip->errors++; - if ((!interface_status(ip)) || - (ip->noifmedia && ip->errors > 20)) { + if (ip->errors > 20) { /* our interface has gone away. */ warning("Interface %s no longer appears valid.", ip->name); ip->dead = 1; - interfaces_invalidated = 1; close(l->fd); remove_protocol(l); - free(ip); + adapter = AdapterFindInfo(ip); + if (adapter) { + RemoveEntryList(&adapter->ListEntry); + free(adapter); + } } return; } @@ -270,75 +241,6 @@ got_one(struct protocol *l) } } -#if 0 -int -interface_status(struct interface_info *ifinfo) -{ - char *ifname = ifinfo->name; - int ifsock = ifinfo->rfdesc; - struct ifreq ifr; - struct ifmediareq ifmr; - - /* get interface flags */ - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { - syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", ifname); - goto inactive; - } - - /* - * if one of UP and RUNNING flags is dropped, - * the interface is not active. - */ - if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) - goto inactive; - - /* Next, check carrier on the interface, if possible */ - if (ifinfo->noifmedia) - goto active; - memset(&ifmr, 0, sizeof(ifmr)); - strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); - if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { - if (errno != EINVAL) { - syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m", - ifname); - - ifinfo->noifmedia = 1; - goto active; - } - /* - * EINVAL (or ENOTTY) simply means that the interface - * does not support the SIOCGIFMEDIA ioctl. We regard it alive. - */ - ifinfo->noifmedia = 1; - goto active; - } - if (ifmr.ifm_status & IFM_AVALID) { - switch (ifmr.ifm_active & IFM_NMASK) { - case IFM_ETHER: - if (ifmr.ifm_status & IFM_ACTIVE) - goto active; - else - goto inactive; - break; - default: - goto inactive; - } - } -inactive: - return (0); -active: - return (1); -} -#else -int -interface_status(struct interface_info *ifinfo) -{ - return (1); -} -#endif - void add_timeout(time_t when, void (*where)(void *), void *what) { diff --git a/reactos/base/services/dhcp/include/rosdhcp.h b/reactos/base/services/dhcp/include/rosdhcp.h index 8a88459730e..ce24ae8edb4 100644 --- a/reactos/base/services/dhcp/include/rosdhcp.h +++ b/reactos/base/services/dhcp/include/rosdhcp.h @@ -73,6 +73,7 @@ typedef DWORD (*PipeSendFunc)( COMM_DHCP_REPLY *Reply ); #define srandom srand void AdapterInit(VOID); +void AdapterDiscover(VOID); HANDLE PipeInit(VOID); extern PDHCP_ADAPTER AdapterGetFirst(); extern PDHCP_ADAPTER AdapterGetNext(PDHCP_ADAPTER);