- 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
This commit is contained in:
Cameron Gutman 2009-07-24 21:06:20 +00:00
parent 15a5343ec1
commit f9fe2ff6a8
4 changed files with 56 additions and 149 deletions

View file

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

View file

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

View file

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

View file

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