]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/common/v2_0/src/dhcp_support.c
Initial revision
[karo-tx-redboot.git] / packages / net / common / v2_0 / src / dhcp_support.c
1 /*==========================================================================
2 //
3 //      dhcp_support.c
4 //
5 //      Support code == friendly API for DHCP client
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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####
42 //
43 // Author(s):   hmt
44 // Contributors: gthomas
45 // Date:        2000-07-01
46 // Purpose:     DHCP support
47 // Description: 
48 //
49 //####DESCRIPTIONEND####
50 //
51 //========================================================================*/
52
53 #include <pkgconf/system.h>
54 #include <pkgconf/net.h>
55
56 #ifdef CYGPKG_NET_DHCP
57
58 #include <network.h>
59 #include <dhcp.h>
60
61 // ---------------------------------------------------------------------------
62 #ifdef CYGHWR_NET_DRIVER_ETH0
63 cyg_uint8   eth0_dhcpstate = 0;
64 #endif
65 #ifdef CYGHWR_NET_DRIVER_ETH1
66 cyg_uint8   eth1_dhcpstate = 0;
67 #endif
68
69 cyg_sem_t dhcp_needs_attention;
70
71 #ifdef CYGHWR_NET_DRIVER_ETH0
72 struct dhcp_lease eth0_lease = { &dhcp_needs_attention, 0,0,0,0,0,0 };
73 #endif
74 #ifdef CYGHWR_NET_DRIVER_ETH1
75 struct dhcp_lease eth1_lease = { &dhcp_needs_attention, 0,0,0,0,0,0 };
76 #endif
77
78 // ---------------------------------------------------------------------------
79 //
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... 
83 //
84 // ---------------------------------------------------------------------------
85
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,
91 // or whatever...
92 int dhcp_bind( void )
93 {
94 #ifdef CYGHWR_NET_DRIVER_ETH0
95     cyg_uint8 old_eth0_dhcpstate = eth0_dhcpstate;
96 #endif
97 #ifdef CYGHWR_NET_DRIVER_ETH1
98     cyg_uint8 old_eth1_dhcpstate = eth1_dhcpstate;
99 #endif
100
101     // If there are no interfaces at all, init it every time, doesn't
102     // matter.  In case we are called from elsewhere...
103     if ( 1
104 #ifdef CYGHWR_NET_DRIVER_ETH0
105          && eth0_dhcpstate == 0
106 #endif
107 #ifdef CYGHWR_NET_DRIVER_ETH1
108          && eth1_dhcpstate == 0
109 #endif
110         )
111         cyg_semaphore_init( &dhcp_needs_attention, 0 );
112
113     // Run the state machine...
114 #ifdef CYGHWR_NET_DRIVER_ETH0
115     if (eth0_up
116         && DHCPSTATE_FAILED != eth0_dhcpstate )
117             eth0_up = do_dhcp(eth0_name, &eth0_bootp_data, &eth0_dhcpstate, &eth0_lease);
118 #endif            
119 #ifdef CYGHWR_NET_DRIVER_ETH1
120     if (eth1_up
121         && DHCPSTATE_FAILED != eth1_dhcpstate )
122             eth1_up = do_dhcp(eth1_name, &eth1_bootp_data, &eth1_dhcpstate, &eth1_lease);
123 #endif            
124
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
128     if ( eth0_up
129          && eth0_dhcpstate == DHCPSTATE_BOUND
130          && old_eth0_dhcpstate != eth0_dhcpstate ) {
131         if (!init_net(eth0_name, &eth0_bootp_data)) {
132             eth0_up = false;
133         }
134     }
135 #endif
136 #ifdef CYGHWR_NET_DRIVER_ETH1
137     if ( eth1_up
138          && eth1_dhcpstate == DHCPSTATE_BOUND
139          && old_eth1_dhcpstate != eth1_dhcpstate ) {
140         if (!init_net(eth1_name, &eth1_bootp_data)) {
141             eth1_up = false;
142         }
143     }
144 #endif
145
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
150 #endif
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
155 #endif
156     return 1; // all is well
157 }
158
159
160 // Shutdown any interface whose state is DHCPSTATE_NOTBOUND.
161 int dhcp_halt( void )
162 {
163 #ifdef CYGHWR_NET_DRIVER_ETH0
164     if ( eth0_up
165          && eth0_dhcpstate != DHCPSTATE_FAILED ) {
166         do_dhcp_down_net(eth0_name, &eth0_bootp_data, &eth0_dhcpstate, &eth0_lease);
167     }
168     eth0_up = false;
169 #endif
170 #ifdef CYGHWR_NET_DRIVER_ETH1
171     if ( eth1_up
172          && eth1_dhcpstate != DHCPSTATE_FAILED ) {
173         do_dhcp_down_net(eth1_name, &eth1_bootp_data, &eth1_dhcpstate, &eth1_lease);
174     }
175     eth1_up = false;
176 #endif
177     return 1;
178 }
179
180
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 )
184 {
185 #ifdef CYGHWR_NET_DRIVER_ETH0
186     if (eth0_up)
187         do_dhcp_release(eth0_name, &eth0_bootp_data, &eth0_dhcpstate, &eth0_lease);
188 #endif
189 #ifdef CYGHWR_NET_DRIVER_ETH1
190     if (eth1_up)
191         do_dhcp_release(eth1_name, &eth1_bootp_data, &eth1_dhcpstate, &eth1_lease);
192 #endif
193     return 1;
194 }
195
196
197 // ------------------------------------------------------------------------
198 // The management thread function
199 void dhcp_mgt_entry( cyg_addrword_t loop_on_failure )
200 {
201     int j;
202     while ( 1 ) {
203         while ( 1 ) {
204             cyg_semaphore_wait( &dhcp_needs_attention );
205             if ( ! dhcp_bind() ) // a lease expired
206                 break; // If we need to re-bind
207         }
208         dhcp_halt(); // tear everything down
209         if ( !loop_on_failure )
210             return; // exit the thread/return
211         init_all_network_interfaces(); // re-initialize
212         for ( j = 0; j < CYGPKG_NET_NLOOP; j++ )
213             init_loopback_interface( j );
214 #ifdef CYGPKG_SNMPAGENT
215         SnmpdShutDown(0); // Cycle the snmpd state
216 #endif
217     }
218 }
219
220 #ifdef CYGOPT_NET_DHCP_DHCP_THREAD
221 // Then we provide such a thread...
222 cyg_handle_t dhcp_mgt_thread_h = 0;
223 cyg_thread   dhcp_mgt_thread;
224
225 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + sizeof(struct bootp))
226 static cyg_uint8 dhcp_mgt_stack[ STACK_SIZE ];
227
228 void dhcp_start_dhcp_mgt_thread( void )
229 {
230     if ( ! dhcp_mgt_thread_h ) {
231         cyg_semaphore_init( &dhcp_needs_attention, 0 );
232         cyg_thread_create(
233             CYGPKG_NET_DHCP_THREAD_PRIORITY, /* scheduling info (eg pri) */
234             dhcp_mgt_entry,             /* entry point function */
235             CYGOPT_NET_DHCP_DHCP_THREAD_PARAM, /* entry data */
236             "DHCP lease mgt",           /* optional thread name */
237             dhcp_mgt_stack,             /* stack base, NULL = alloc */
238             STACK_SIZE,                 /* stack size, 0 = default */
239             &dhcp_mgt_thread_h,         /* returned thread handle */
240             &dhcp_mgt_thread           /* put thread here */
241             );
242
243         cyg_thread_resume(dhcp_mgt_thread_h);
244     }
245 }
246
247
248 #endif // CYGOPT_NET_DHCP_DHCP_THREAD
249
250 #endif // CYGPKG_NET_DHCP
251
252 // EOF dhcp_support.c