1 #ifndef CYGONCE_NET_TCPIP_DHCP_H
2 #define CYGONCE_NET_TCPIP_DHCP_H
4 //==========================================================================
8 // DHCP protocol support
10 //==========================================================================
11 //####BSDCOPYRIGHTBEGIN####
13 // -------------------------------------------
15 // Portions of this software may have been derived from OpenBSD or other sources,
16 // and are covered by the appropriate copyright disclaimers included herein.
18 // -------------------------------------------
20 //####BSDCOPYRIGHTEND####
21 //==========================================================================
22 //#####DESCRIPTIONBEGIN####
25 // Contributors: gthomas
27 // Purpose: Support DHCP initialization in eCos TCPIP stack
31 //####DESCRIPTIONEND####
33 //==========================================================================
36 // DHCP. RFC2131, RFC1533, RFC1534
40 #include <pkgconf/system.h>
41 #include <pkgconf/net.h>
43 #ifdef CYGPKG_NET_DHCP
45 #include <machine/types.h>
47 #include <cyg/kernel/kapi.h>
51 // DHCP messages; these are sent in the tag TAG_DHCP_MESS_TYPE already
54 #define DHCPDISCOVER 1
62 // DHCP interface state machine states; these are published so that app
63 // code can know what to do... (see page 35 of RFC2131)
65 // These we will use in the normal course of events
66 #define DHCPSTATE_INIT 1
67 #define DHCPSTATE_SELECTING 2 // wait for replies to b/c DISCOVER
68 #define DHCPSTATE_REQUESTING 3
69 #define DHCPSTATE_REQUEST_RECV 4 // wait for replies to b/c REQUEST
70 #define DHCPSTATE_BOUND 5
71 #define DHCPSTATE_RENEWING 6 // wait for replies to u/c REQUEST
72 #define DHCPSTATE_RENEW_RECV 7
73 #define DHCPSTATE_REBINDING 8 // wait for replies to b/c REQUEST
74 #define DHCPSTATE_REBIND_RECV 9
75 #define DHCPSTATE_BOOTP_FALLBACK 10 // fall back to plain bootp
76 #define DHCPSTATE_NOTBOUND 11 // To let app tidy up
77 #define DHCPSTATE_FAILED 12 // Net is down
78 #define DHCPSTATE_DO_RELEASE 13 // Force release of the current lease
80 //#define DHCPSTATE_INITREBOOT
81 //#define DHCPSTATE_REBOOTING
83 // These are to let the app inspect the state of the interfaces when
84 // managing them itself, by analogy with eth0_up &c; eth0_bootp_data and so
85 // on will still be used with DHCP.
86 #ifdef CYGHWR_NET_DRIVER_ETH0
87 extern cyg_uint8 eth0_dhcpstate;
89 #ifdef CYGHWR_NET_DRIVER_ETH1
90 extern cyg_uint8 eth1_dhcpstate;
93 // This is public so the app can wait on it or poll it when managing DHCP
94 // itself. It will be zero while the app should wait, and posted when a
95 // call to do_dhcp() is needed. If, instead, the app wishes to manage DHCP
96 // with a thread per interface somehow, then separate semaphores may be used.
97 // See the dhcp_lease structure definition below.
98 extern cyg_sem_t dhcp_needs_attention;
100 // This routine is used at startup time, and after relinquishing leases or
101 // after a lease timeout: it does DHCP or bootp or static setup according
103 extern void init_all_network_interfaces(void);
105 // This routine does the work of renewing leases &c.
106 // return value: 1 => everything OK, no change.
107 // 0 => close your connections, then call do_dhcp_halt() to halt the
108 // interface(s) in question (it knows because the state will be NOTBOUND).
109 // After that you can return to the start and use
110 // init_all_network_interfaces() as usual.
111 extern int dhcp_bind( void );
113 // Shutdown any interface which is not already shut down - whether
114 // initialized by DHCP or not. Reason: because of the broadcast-while-not-
115 // -fully-initialized nature of the DHCP conversation, all other interfaces
116 // must be shut down during that. So one down, all down, is required.
117 extern int dhcp_halt( void );
119 // Release (and set state to DHCPSTATE_NOTBOUND) all interfaces - we are
120 // closing down. (unlikely but useful for testing)
121 // Interfaces are left up; use dhcp_halt() to bring them right down, then
122 // call init_all_network_interfaces() as usual to restart all.
123 extern int dhcp_release( void );
125 // The intent with this API is that a simple DHCP client thread, which
126 // maintains the state of the interfaces, can go as follows:
127 // (after init_all_networks is called from elsewhere)
131 // cyg_semaphore_wait( &dhcp_needs_attention );
132 // if ( ! dhcp_bind() ) // a lease expired
133 // break; // If we need to re-bind
135 // dhcp_halt(); // tear everything down
136 // init_all_network_interfaces(); // re-initialize
139 // and if the application does not want to suffer the overhead of a
140 // separate thread and its stack for this, this functionality can be placed
141 // in the app's server loop in an obvious fashion. That is the goal of
142 // breaking out these internal elements. For example, some server might
143 // be arranged to poll DHCP from time to time like this:
146 // init_all_network_interfaces();
147 // open-my-listen-sockets();
149 // serve-one-request();
150 // // sleeps if no connections, but not forever; so this loop is
151 // // polled a few times a minute...
152 // if ( cyg_semaphore_trywait( &dhcp_needs_attention )) {
153 // if ( ! dhcp_bind() ) {
154 // close-my-listen-sockets();
162 // ------------------------------------------------------------------------
164 // Set hostname to be used with the DHCP TAG_HOST_NAME option.
165 // Call this before calling init_all_network_interfaces() to
166 // set the hostname value.
167 #ifdef CYGOPT_NET_DHCP_OPTION_HOST_NAME
168 extern void dhcp_set_hostname(char *hostname);
170 #define dhcp_set_hostname(hostname) CYG_EMPTY_STATEMENT
173 #ifdef CYGOPT_NET_DHCP_DHCP_THREAD
174 // Then we provide such a thread...
176 // Provide a separate thread to renew DHCP leases; otherwise the
177 // application MUST periodically examine the semaphore dhcp_needs_attention
178 // and call dhcp_bind() if it is signalled. If enabled, this thread does
179 // all that for you. Independent of this option, initialization of the
180 // interfaces still occurs in init_all_network_interfaces() and your
181 // startup code must call that. It will start the DHCP management thread
182 // if necessary. If a lease fails to be renewed, the management thread
183 // will shut down all interfaces and attempt to initialize all the
184 // interfaces again from scratch. This may cause chaos in the app, which
185 // is why managing the DHCP state in an application aware thread is
186 // actually better, just far less convenient for testing.
188 extern cyg_handle_t dhcp_mgt_thread_h; // To allow its external manipulation.
189 extern cyg_thread dhcp_mgt_thread; // The object itself
191 extern void dhcp_start_dhcp_mgt_thread( void );
195 // The function is provided unconditionally so that the app can put it in a
196 // thread of its own. If the parameter is true, it loops forever; if
197 // false, the call returns if a lease expires, and the caller must tidy up
198 // or reboot the whole machine.
199 extern cyg_thread_entry_t dhcp_mgt_entry;
200 extern void dhcp_mgt_entry( cyg_addrword_t loop_on_failure ); // the function
202 // ---------------------------------------------------------------------------
203 // These are rather more internal routines, internal to the protocol engine
204 // in dhcp_prot.c - those above are in dhcp_support.c
206 #define DHCP_LEASE_T1 1
207 #define DHCP_LEASE_T2 2
208 #define DHCP_LEASE_EX 4
211 // Client settable: Semaphore to signal when attention is needed:
212 cyg_sem_t *needs_attention;
213 // Initialize all the rest to zero:
214 cyg_tick_count_t t1, t2, expiry;
215 volatile cyg_uint8 next;
216 volatile cyg_uint8 which;
218 // except this one, which is just some space:
222 // These dhcp_lease objects are initialized to use
223 // extern cyg_sem_t dhcp_needs_attention;
224 // for the semaphore.
225 #ifdef CYGHWR_NET_DRIVER_ETH0
226 extern struct dhcp_lease eth0_lease;
228 #ifdef CYGHWR_NET_DRIVER_ETH1
229 extern struct dhcp_lease eth1_lease;
233 do_dhcp(const char *interface, struct bootp *res,
234 cyg_uint8 *pstate, struct dhcp_lease *lease);
235 // NB *res and *pstate and *lease are all INOUT; *res must point to a valid
236 // record from "last time".
239 do_dhcp_down_net(const char *intf, struct bootp *res,
240 cyg_uint8 *pstate, struct dhcp_lease *lease);
243 do_dhcp_release(const char *intf, struct bootp *res,
244 cyg_uint8 *pstate, struct dhcp_lease *lease);
246 #endif // CYGPKG_NET_DHCP
248 #endif // CYGONCE_NET_TCPIP_DHCP_H