Mercurial > ecos
diff packages/net/common/current/src/dhcp_support.c @ 208:e0c0827131d1 ecos
Merge from eCos master repository on 2002-05-20-20:11:54-BST
| author | jlarmour |
|---|---|
| date | Mon, 20 May 2002 22:19:26 +0000 |
| parents | |
| children | 7c34839e7e97 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/net/common/current/src/dhcp_support.c @@ -0,0 +1,229 @@ +/*========================================================================== +// +// dhcp_support.c +// +// Support code == friendly API for DHCP client +// +//========================================================================== +//####ECOSPDCOPYRIGHTBEGIN#### +// +// Copyright (C) 2000, 2001, 2002 Red Hat, Inc. +// All Rights Reserved. +// +// Permission is granted to use, copy, modify and redistribute this +// file. +// +//####ECOSPDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: gthomas +// Date: 2000-07-01 +// Purpose: DHCP support +// Description: +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/system.h> +#include <pkgconf/net.h> + +#ifdef CYGPKG_NET_DHCP + +#include <network.h> +#include <dhcp.h> + +// --------------------------------------------------------------------------- +#ifdef CYGHWR_NET_DRIVER_ETH0 +cyg_uint8 eth0_dhcpstate = 0; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 +cyg_uint8 eth1_dhcpstate = 0; +#endif + +cyg_sem_t dhcp_needs_attention; + +#ifdef CYGHWR_NET_DRIVER_ETH0 +struct dhcp_lease eth0_lease = { &dhcp_needs_attention, 0,0,0,0,0,0 }; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 +struct dhcp_lease eth1_lease = { &dhcp_needs_attention, 0,0,0,0,0,0 }; +#endif + +// --------------------------------------------------------------------------- +// +// The point of this module is to deal with all the horrid written out in +// full stuff of having two interfaces; it's ugly but it's also most +// flexible. The dhcp_prot.c module should do all the work... +// +// --------------------------------------------------------------------------- + +// return value: 1 => everything OK, no change. +// 0 => close your connections, then call do_dhcp_halt() to halt the +// interface(s) in question (it knows because the state will be NOTBOUND). +// After that you can return to the start and use +// init_all_network_interfaces(); as usual, or call do_dhcp_bind() by hand, +// or whatever... +int dhcp_bind( void ) +{ +#ifdef CYGHWR_NET_DRIVER_ETH0 + cyg_uint8 old_eth0_dhcpstate = eth0_dhcpstate; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + cyg_uint8 old_eth1_dhcpstate = eth1_dhcpstate; +#endif + + // If there are no interfaces at all, init it every time, doesn't + // matter. In case we are called from elsewhere... + if ( 1 +#ifdef CYGHWR_NET_DRIVER_ETH0 + && eth0_dhcpstate == 0 +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + && eth1_dhcpstate == 0 +#endif + ) + cyg_semaphore_init( &dhcp_needs_attention, 0 ); + + // Run the state machine... +#ifdef CYGHWR_NET_DRIVER_ETH0 + if (eth0_up + && DHCPSTATE_FAILED != eth0_dhcpstate ) + eth0_up = do_dhcp(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease); +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if (eth1_up + && DHCPSTATE_FAILED != eth1_dhcpstate ) + eth1_up = do_dhcp(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease); +#endif + + // If the interface newly came up, initialize it: + // (this duplicates the code in init_all_network_interfaces() really). +#ifdef CYGHWR_NET_DRIVER_ETH0 + if ( eth0_up + && eth0_dhcpstate == DHCPSTATE_BOUND + && old_eth0_dhcpstate != eth0_dhcpstate ) { + if (!init_net(eth0_name, ð0_bootp_data)) { + eth0_up = false; + } + } +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if ( eth1_up + && eth1_dhcpstate == DHCPSTATE_BOUND + && old_eth1_dhcpstate != eth1_dhcpstate ) { + if (!init_net(eth1_name, ð1_bootp_data)) { + eth1_up = false; + } + } +#endif + +#ifdef CYGHWR_NET_DRIVER_ETH0 + if ( old_eth0_dhcpstate == DHCPSTATE_BOUND && + eth0_dhcpstate == DHCPSTATE_NOTBOUND ) + return 0; // a lease timed out; we became unbound +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if ( old_eth1_dhcpstate == DHCPSTATE_BOUND && + eth1_dhcpstate == DHCPSTATE_NOTBOUND ) + return 0; // a lease timed out; we became unbound +#endif + return 1; // all is well +} + + +// Shutdown any interface whose state is DHCPSTATE_NOTBOUND. +int dhcp_halt( void ) +{ +#ifdef CYGHWR_NET_DRIVER_ETH0 + if ( eth0_up + && eth0_dhcpstate != DHCPSTATE_FAILED ) { + do_dhcp_down_net(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease); + } + eth0_up = false; +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if ( eth1_up + && eth1_dhcpstate != DHCPSTATE_FAILED ) { + do_dhcp_down_net(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease); + } + eth1_up = false; +#endif + return 1; +} + + +// Release (and set state to DHCPSTATE_NOTBOUND) all interfaces - we are +// closing down. (unlikely but maybe useful for testing) +int dhcp_release( void ) +{ +#ifdef CYGHWR_NET_DRIVER_ETH0 + if (eth0_up) + do_dhcp_release(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease); +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + if (eth1_up) + do_dhcp_release(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease); +#endif + return 1; +} + + +// ------------------------------------------------------------------------ +// The management thread function +void dhcp_mgt_entry( cyg_addrword_t loop_on_failure ) +{ + int j; + while ( 1 ) { + while ( 1 ) { + cyg_semaphore_wait( &dhcp_needs_attention ); + if ( ! dhcp_bind() ) // a lease expired + break; // If we need to re-bind + } + dhcp_halt(); // tear everything down + if ( !loop_on_failure ) + return; // exit the thread/return + init_all_network_interfaces(); // re-initialize + for ( j = 0; j < CYGPKG_NET_NLOOP; j++ ) + init_loopback_interface( j ); +#ifdef CYGPKG_SNMPAGENT + SnmpdShutDown(0); // Cycle the snmpd state +#endif + } +} + +#ifdef CYGOPT_NET_DHCP_DHCP_THREAD +// Then we provide such a thread... +cyg_handle_t dhcp_mgt_thread_h = 0; +cyg_thread dhcp_mgt_thread; + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + sizeof(struct bootp)) +static cyg_uint8 dhcp_mgt_stack[ STACK_SIZE ]; + +void dhcp_start_dhcp_mgt_thread( void ) +{ + if ( ! dhcp_mgt_thread_h ) { + cyg_semaphore_init( &dhcp_needs_attention, 0 ); + cyg_thread_create( + CYGPKG_NET_DHCP_THREAD_PRIORITY, /* scheduling info (eg pri) */ + dhcp_mgt_entry, /* entry point function */ + CYGOPT_NET_DHCP_DHCP_THREAD_PARAM, /* entry data */ + "DHCP lease mgt", /* optional thread name */ + dhcp_mgt_stack, /* stack base, NULL = alloc */ + STACK_SIZE, /* stack size, 0 = default */ + &dhcp_mgt_thread_h, /* returned thread handle */ + &dhcp_mgt_thread /* put thread here */ + ); + + cyg_thread_resume(dhcp_mgt_thread_h); + } +} + + +#endif // CYGOPT_NET_DHCP_DHCP_THREAD + +#endif // CYGPKG_NET_DHCP + +// EOF dhcp_support.c
