1 /*==========================================================================
5 // Support code == friendly API for DHCP client
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
46 // Purpose: DHCP support
49 //####DESCRIPTIONEND####
51 //========================================================================*/
53 #include <pkgconf/system.h>
54 #include <pkgconf/net.h>
56 #ifdef CYGPKG_NET_DHCP
61 // ---------------------------------------------------------------------------
62 #ifdef CYGHWR_NET_DRIVER_ETH0
63 cyg_uint8 eth0_dhcpstate = 0;
65 #ifdef CYGHWR_NET_DRIVER_ETH1
66 cyg_uint8 eth1_dhcpstate = 0;
69 cyg_sem_t dhcp_needs_attention;
71 #ifdef CYGHWR_NET_DRIVER_ETH0
72 struct dhcp_lease eth0_lease = { &dhcp_needs_attention, 0,0,0,0,0,0 };
74 #ifdef CYGHWR_NET_DRIVER_ETH1
75 struct dhcp_lease eth1_lease = { &dhcp_needs_attention, 0,0,0,0,0,0 };
78 // ---------------------------------------------------------------------------
80 // The point of this module is to deal with all the horrid written out in
81 // full stuff of having two interfaces; it's ugly but it's also most
82 // flexible. The dhcp_prot.c module should do all the work...
84 // ---------------------------------------------------------------------------
86 // return value: 1 => everything OK, no change.
87 // 0 => close your connections, then call do_dhcp_halt() to halt the
88 // interface(s) in question (it knows because the state will be NOTBOUND).
89 // After that you can return to the start and use
90 // init_all_network_interfaces(); as usual, or call do_dhcp_bind() by hand,
94 #ifdef CYGHWR_NET_DRIVER_ETH0
95 cyg_uint8 old_eth0_dhcpstate = eth0_dhcpstate;
97 #ifdef CYGHWR_NET_DRIVER_ETH1
98 cyg_uint8 old_eth1_dhcpstate = eth1_dhcpstate;
101 // If there are no interfaces at all, init it every time, doesn't
102 // matter. In case we are called from elsewhere...
104 #ifdef CYGHWR_NET_DRIVER_ETH0
105 && eth0_dhcpstate == 0
107 #ifdef CYGHWR_NET_DRIVER_ETH1
108 && eth1_dhcpstate == 0
111 cyg_semaphore_init( &dhcp_needs_attention, 0 );
113 // Run the state machine...
114 #ifdef CYGHWR_NET_DRIVER_ETH0
116 && DHCPSTATE_FAILED != eth0_dhcpstate )
117 eth0_up = do_dhcp(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease);
119 #ifdef CYGHWR_NET_DRIVER_ETH1
121 && DHCPSTATE_FAILED != eth1_dhcpstate )
122 eth1_up = do_dhcp(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease);
125 // If the interface newly came up, initialize it:
126 // (this duplicates the code in init_all_network_interfaces() really).
127 #ifdef CYGHWR_NET_DRIVER_ETH0
129 && eth0_dhcpstate == DHCPSTATE_BOUND
130 && old_eth0_dhcpstate != eth0_dhcpstate ) {
131 if (!init_net(eth0_name, ð0_bootp_data)) {
136 #ifdef CYGHWR_NET_DRIVER_ETH1
138 && eth1_dhcpstate == DHCPSTATE_BOUND
139 && old_eth1_dhcpstate != eth1_dhcpstate ) {
140 if (!init_net(eth1_name, ð1_bootp_data)) {
146 #ifdef CYGHWR_NET_DRIVER_ETH0
147 if ( old_eth0_dhcpstate == DHCPSTATE_BOUND &&
148 eth0_dhcpstate == DHCPSTATE_NOTBOUND )
149 return 0; // a lease timed out; we became unbound
151 #ifdef CYGHWR_NET_DRIVER_ETH1
152 if ( old_eth1_dhcpstate == DHCPSTATE_BOUND &&
153 eth1_dhcpstate == DHCPSTATE_NOTBOUND )
154 return 0; // a lease timed out; we became unbound
156 return 1; // all is well
160 // Shutdown any interface whose state is DHCPSTATE_NOTBOUND.
161 int dhcp_halt( void )
163 #ifdef CYGHWR_NET_DRIVER_ETH0
165 && eth0_dhcpstate != DHCPSTATE_FAILED ) {
166 do_dhcp_down_net(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease);
170 #ifdef CYGHWR_NET_DRIVER_ETH1
172 && eth1_dhcpstate != DHCPSTATE_FAILED ) {
173 do_dhcp_down_net(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease);
181 // Release (and set state to DHCPSTATE_NOTBOUND) all interfaces - we are
182 // closing down. (unlikely but maybe useful for testing)
183 int dhcp_release( void )
185 #ifdef CYGHWR_NET_DRIVER_ETH0
187 do_dhcp_release(eth0_name, ð0_bootp_data, ð0_dhcpstate, ð0_lease);
189 #ifdef CYGHWR_NET_DRIVER_ETH1
191 do_dhcp_release(eth1_name, ð1_bootp_data, ð1_dhcpstate, ð1_lease);
197 // ------------------------------------------------------------------------
198 // The management thread function
201 // This single management thread attempts to keep all configured
202 // interfaces alive via DHCP. While this may be sufficient for
203 // many systems, it falls short of perfect. There should probably
204 // be a separate thread for each possible interface, along with
205 // appropriate CDL to control how each inteface is managed.
207 void dhcp_mgt_entry( cyg_addrword_t loop_on_failure )
210 bool any_interfaces_up;
214 cyg_semaphore_wait( &dhcp_needs_attention );
215 if ( ! dhcp_bind() ) // a lease expired
216 break; // If we need to re-bind
218 dhcp_halt(); // tear everything down
219 if ( !loop_on_failure )
220 return; // exit the thread/return
222 init_all_network_interfaces(); // re-initialize
223 // If at least one interface is up, then the DHCP machine will run
224 any_interfaces_up = false;
225 #ifdef CYGHWR_NET_DRIVER_ETH0
226 any_interfaces_up |= eth0_up;
228 #ifdef CYGHWR_NET_DRIVER_ETH1
229 any_interfaces_up |= eth1_up;
231 } while (!any_interfaces_up);
232 for ( j = 0; j < CYGPKG_NET_NLOOP; j++ )
233 init_loopback_interface( j );
234 #ifdef CYGPKG_SNMPAGENT
235 SnmpdShutDown(0); // Cycle the snmpd state
240 #ifdef CYGOPT_NET_DHCP_DHCP_THREAD
241 // Then we provide such a thread...
242 cyg_handle_t dhcp_mgt_thread_h = 0;
243 cyg_thread dhcp_mgt_thread;
245 static cyg_uint8 dhcp_mgt_stack[ CYGPKG_NET_DHCP_THREAD_STACK_SIZE ];
247 void dhcp_start_dhcp_mgt_thread( void )
249 if ( ! dhcp_mgt_thread_h ) {
250 cyg_semaphore_init( &dhcp_needs_attention, 0 );
252 CYGPKG_NET_DHCP_THREAD_PRIORITY, /* scheduling info (eg pri) */
253 dhcp_mgt_entry, /* entry point function */
254 CYGOPT_NET_DHCP_DHCP_THREAD_PARAM, /* entry data */
255 "DHCP lease mgt", /* optional thread name */
256 dhcp_mgt_stack, /* stack base, NULL = alloc */
257 CYGPKG_NET_DHCP_THREAD_STACK_SIZE, /* stack size, 0 = default */
258 &dhcp_mgt_thread_h, /* returned thread handle */
259 &dhcp_mgt_thread /* put thread here */
262 cyg_thread_resume(dhcp_mgt_thread_h);
267 #endif // CYGOPT_NET_DHCP_DHCP_THREAD
269 #endif // CYGPKG_NET_DHCP
271 // EOF dhcp_support.c