initial commit after making...
Stefan Schuermans authored 12 years ago
|
5)
6) #include <string.h>
7)
8) #include "config.h"
9) #include "checksum.h"
10) #include "debug.h"
11) #include "dhcp.h"
12) #include "ethernet.h"
13) #include "ip.h"
14) #include "macros.h"
15) #include "nethelp.h"
16) #include "random.h"
17) #include "udp.h"
18)
19) // configuration
20) static const unsigned char DhcpRetrySecsMax = 10; // avarage timeout
21) // after which to
22) // retry DHCP action
23) static const unsigned char DhcpRetriesMax = 5; // maximum number of retries
24) // before aborting DHCP
25) // action
26) static const unsigned long DhcpLeaseRestMin = 300; // when to ask to
27) // extend lease
28) static const unsigned char DhcpLeaseRenewFraction = 8; // to renw lease when
29) // only this fraction
30) // of lease is left
31)
32) // DHCP tick counter to get full seconds
33) static unsigned char DhcpTicks = 0;
34)
35) // time of current DHCP action
36) static unsigned char DhcpInProgress = 0; // if DHCP action is in
37) // progress
38) static unsigned char DhcpRetries = 0; // number of retries left
39) static unsigned char DhcpRetrySecs = 0; // rest of time for current retry
40)
41) // current XId
42) static unsigned char DhcpHaveXId = 0; // if an XId exists at the moment
43) static unsigned long DhcpXId = 0; // the current XId data
44) static unsigned int DhcpXIdSecs = 0; // time of XId
45)
46) // DHCP server and lease time
47) static unsigned char DhcpActive = 0; // if own IP is leased from DHCP
48) static unsigned char DhcpServer[4]; // IP address of DHCP server own IP
49) // is leased from
50) static unsigned long DhcpLeaseTime = 0; // total lease time
51) static unsigned long DhcpLeaseRest = 0; // rest of lease time
52)
53) // send a DHCP packet
54) // pData must point to a struct DhcpPacket with IpHdr.Dest, DhcpHdr.XId
55) // DhcpHdr.Secs, DhcpHdr.Flags and DhcpHdr.YIAddr already initialized
56) static void DhcpSend(unsigned char *pData, unsigned short Length) // (extern)
57) {
58) struct DhcpPacket *pDhcpPack;
59)
60) // packet too short
61) if (Length < sizeof(struct DhcpPacket))
62) return;
63)
64) // convert pointer to DHCP packet
65) // (this saves us from always casting pData)
66) pDhcpPack = (struct DhcpPacket *)pData;
67)
68) debug_dhcp_printf("send xid=%08lX len=%d",
69) ntohl(pDhcpPack->DhcpHdr.XId), Length);
70)
71) // we are DHCP client
72) // - source port must be 68
73) // - destination port must be 67
74) pDhcpPack->UdpHdr.SrcPort = htons(68);
75) pDhcpPack->UdpHdr.DestPort = htons(67);
76) // set up DHCP header fields as client
77) pDhcpPack->DhcpHdr.Op = 1;
78) pDhcpPack->DhcpHdr.HType = 1;
79) pDhcpPack->DhcpHdr.HLen = 6;
80) pDhcpPack->DhcpHdr.HOps = 0;
81) memset(pDhcpPack->DhcpHdr.CIAddr, 0, 4);
82) memset(pDhcpPack->DhcpHdr.SIAddr, 0, 4);
83) memset(pDhcpPack->DhcpHdr.GIAddr, 0, 4);
84) mac_cpy(pDhcpPack->DhcpHdr.CHAddr, ConfigMac);
85) memset(pDhcpPack->DhcpHdr.CHAddr + 6, 0, 10);
86) memset(pDhcpPack->DhcpHdr.SName, 0, 64);
87) memset(pDhcpPack->DhcpHdr.File, 0, 128);
88) pDhcpPack->DhcpHdr.MCookie = htonl(0x63825363);
89)
90) // send DHCP packet
91) UdpSend(pData, Length);
92) }
93)
94) // send a DHCP discover
95) static void DhcpDiscover(void)
96) {
97) struct {
98) struct DhcpPacket DhcpPack;
99) unsigned char OptType[3];
100) unsigned char OptEnd[2];
101) } DhcpDiscover;
102)
103) debug_dhcp_printf("discover");
104)
105) ip_cpy(DhcpDiscover.DhcpPack.IpHdr.Dest, "\xFF\xFF\xFF\xFF"); // broadcast
106) DhcpDiscover.DhcpPack.DhcpHdr.XId = htonl(DhcpXId);
107) DhcpDiscover.DhcpPack.DhcpHdr.Secs = htons(DhcpXIdSecs); // use time
108) // of XId
109) DhcpDiscover.DhcpPack.DhcpHdr.Flags = htons(0x8000); // broadcast
110) memset(DhcpDiscover.DhcpPack.DhcpHdr.YIAddr, 0, 4);
111) DhcpDiscover.OptType[0] = 0x35; // DHCP discover
112) DhcpDiscover.OptType[1] = 0x01;
113) DhcpDiscover.OptType[2] = 0x01;
114) DhcpDiscover.OptEnd[0] = 0xFF; // end of options
115) DhcpDiscover.OptEnd[1] = 0x00;
116)
117) DhcpSend((unsigned char *)&DhcpDiscover, sizeof(DhcpDiscover));
118) }
119)
120) // send a DHCP request
121) static void DhcpRequest(void)
122) {
123) struct {
124) struct DhcpPacket DhcpPack;
125) unsigned char OptType[3];
126) unsigned char OptReq[6];
127) unsigned char OptServer[6];
128) unsigned char OptEnd[2];
129) } DhcpRequest;
130)
131) debug_dhcp_printf("request ip=%d.%d.%d.%d",
132) ConfigIp[0], ConfigIp[1], ConfigIp[2], ConfigIp[3]);
133)
134) ip_cpy(DhcpRequest.DhcpPack.IpHdr.Dest, DhcpServer); // send to DHCP
135) // server
136) DhcpRequest.DhcpPack.DhcpHdr.XId = htonl(DhcpXId);
137) DhcpRequest.DhcpPack.DhcpHdr.Secs = htons(DhcpXIdSecs); // use time
138) // of XId
139) DhcpRequest.DhcpPack.DhcpHdr.Flags = htons(0x0000);
140) ip_cpy(DhcpRequest.DhcpPack.DhcpHdr.YIAddr, ConfigIp);
141) DhcpRequest.OptType[0] = 0x35; // DHCP request
142) DhcpRequest.OptType[1] = 0x01;
143) DhcpRequest.OptType[2] = 0x03;
144) DhcpRequest.OptReq[0] = 0x32; // requested IP
145) DhcpRequest.OptReq[1] = 0x04;
146) ip_cpy(&DhcpRequest.OptReq[2], ConfigIp);
147) DhcpRequest.OptServer[0] = 0x36; // DHCP server
148) DhcpRequest.OptServer[1] = 0x04;
149) ip_cpy(&DhcpRequest.OptServer[2], DhcpServer);
150) DhcpRequest.OptEnd[0] = 0xFF; // end of options
151) DhcpRequest.OptEnd[1] = 0x00;
152)
153) DhcpSend((unsigned char *)&DhcpRequest, sizeof(DhcpRequest));
154) }
155)
156) // abort DHCP action
157) static void DhcpAbort(void)
158) {
159) // abort DHCP action
160) DhcpInProgress = 0;
161) DhcpRetries = 0;
162) DhcpRetrySecs = 0;
163)
164) // forget XId
165) DhcpHaveXId = 0;
166) DhcpXId = 0;
167) DhcpXIdSecs = 0;
168)
169) // give up IP address if it was leased
170) if (DhcpActive) {
171) ip_cpy(ConfigIp, "\0\0\0\0");
172) ip_cpy(ConfigMask, "\0\0\0\0");
173) ip_cpy(ConfigGw, "\0\0\0\0");
174) DhcpActive = 0;
175) DhcpLeaseTime = 0;
176) DhcpLeaseRest = 0;
177) }
178) }
179)
180) // retry DHCP action
181) static void DhcpRetry(void)
182) {
183) // DHCP lease not active ---> re-send DHCP discover
184) if (!DhcpActive) {
185)
186) // get time for next try
187) RandomGetData((unsigned char *)&DhcpRetrySecs, sizeof(DhcpRetrySecs));
188) DhcpRetrySecs = DhcpRetrySecs % DhcpRetrySecsMax + DhcpRetrySecsMax / 2;
189) // re-send DHCP discover
190) DhcpDiscover();
191)
192) }
193) // DHCP lease active and lease time almost over ---> re-send DHCP request
194) if (DhcpActive && (DhcpLeaseRest < DhcpLeaseRestMin ||
195) DhcpLeaseRest <
196) DhcpLeaseTime / DhcpLeaseRenewFraction)) {
197)
198) // get time for next try
199) RandomGetData((unsigned char *)&DhcpRetrySecs, sizeof(DhcpRetrySecs));
200) DhcpRetrySecs = DhcpRetrySecs % DhcpRetrySecsMax + DhcpRetrySecsMax / 2;
201) // re-send DHCP request
202) DhcpRequest();
203)
204) }
205) }
206)
207) // start new DHCP action
208) static void DhcpStart(void)
209) {
210) // DHCP lease not active ---> DHCP discover
211) if (!DhcpActive) {
212)
213) // DHCP operation starts
214) DhcpInProgress = 1;
215) DhcpRetries = DhcpRetriesMax;
216) RandomGetData((unsigned char *)&DhcpRetrySecs, sizeof(DhcpRetrySecs));
217) DhcpRetrySecs = DhcpRetrySecs % DhcpRetrySecsMax + DhcpRetrySecsMax / 2;
218) // get new XId
219) RandomGetData((unsigned char *)&DhcpXId, sizeof(DhcpXId));
220) DhcpXIdSecs++;
221) DhcpHaveXId = 1;
222) // send DHCP discover
223) DhcpDiscover();
224)
225) }
226) // DHCP lease active and lease time almost over ---> DHCP request
227) if (DhcpActive && (DhcpLeaseRest < DhcpLeaseRestMin ||
228) DhcpLeaseRest <
229) DhcpLeaseTime / DhcpLeaseRenewFraction)) {
230)
231) // DHCP operation starts
232) DhcpInProgress = 1;
233) DhcpRetries = DhcpRetriesMax;
234) RandomGetData((unsigned char *)&DhcpRetrySecs, sizeof(DhcpRetrySecs));
235) DhcpRetrySecs = DhcpRetrySecs % DhcpRetrySecsMax + DhcpRetrySecsMax / 2;
236) // get new XId if none available
237) if (!DhcpHaveXId) {
238) RandomGetData((unsigned char *)&DhcpXId, sizeof(DhcpXId));
239) DhcpXIdSecs++;
240) DhcpHaveXId = 1;
241) }
242) // send DHCP request
243) DhcpRequest();
244)
245) }
246) }
247)
248) // tick procedure - every 1000ms
249) static void DhcpTick1000(void)
250) {
251) // DHCP operation in progress
252) if (DhcpInProgress) {
253)
254) // count down time of current try of current action
255) DhcpRetrySecs--;
256) if (DhcpRetrySecs <= 0) {
257)
258) // count down retries
259) DhcpRetries--;
260)
261) // no more retries left ---> abort, retry otherwise
262) if (DhcpRetries <= 0)
263) DhcpAbort();
264) else
265) DhcpRetry();
266)
267) }
268)
269) }
270) // increase time of XId
271) DhcpXIdSecs++;
272)
273) // dcrease remaining lease time
274) DhcpLeaseRest--;
275) // lease timed out ---> abort DHCP (will also invalidate IP)
276) if (DhcpLeaseRest <= 0) {
277) debug_dhcp_printf("lease expired");
278) DhcpAbort();
279) }
280) }
281)
282) // tick procedure - call every 200ms
283) void DhcpTick200(void) // (extern)
284) {
285) // get 1 second interval
286) DhcpTicks++;
287) if (DhcpTicks >= 5) {
288) DhcpTicks = 0;
289) DhcpTick1000();
290) }
291) // no DHCP operation in progress
292) if (!DhcpInProgress) {
293) // DHCP lease active or no IP address ---> DHCP allowed (i.e. no static
294) // IP)
295) if (DhcpActive || ip_eq(ConfigIp, "\0\0\0\0")) {
296) // start new DHCP action
297) DhcpStart();
298) }
299) }
300) }
301)
302) // process a received DHCP offer
303) static void DhcpOffer(unsigned char addr[4], unsigned char mask[4],
304) unsigned char gateway[4], unsigned long time,
305) unsigned char server[4])
306) {
307) debug_dhcp_printf("offer addr=%d.%d.%d.%d mask=%d.%d.%d.%d gw=%d.%d.%d.%d",
308) addr[0], addr[1], addr[2], addr[3],
309) mask[0], mask[1], mask[2], mask[3],
310) gateway[0], gateway[1], gateway[2], gateway[3]);
311) debug_dhcp_printf("offer time=%ld server=%d.%d.%d.%d",
312) time, server[0], server[1], server[2], server[3]);
313)
314) // use this IP address, mask and gateway
315) ip_cpy(ConfigIp, addr);
316) ip_cpy(ConfigMask, mask);
317) ip_cpy(ConfigGw, gateway);
318)
319) // store DHCP server and lease time
320) DhcpActive = 1;
321) ip_cpy(DhcpServer, server);
322) DhcpLeaseTime = time;
323) DhcpLeaseRest = DhcpLeaseRestMin; // schedule DHCP request
324)
325) // DHCP action finished
326) DhcpInProgress = 0;
327) DhcpRetries = 0;
328) DhcpRetrySecs = 0;
329) }
330)
331) // process a received DHCP ack
332) static void DhcpAck(unsigned char addr[4], unsigned char mask[4],
333) unsigned char gateway[4], unsigned long time,
334) unsigned char server[4])
335) {
336) debug_dhcp_printf("ack addr=%d.%d.%d.%d mask=%d.%d.%d.%d gw=%d.%d.%d.%d",
337) addr[0], addr[1], addr[2], addr[3],
338) mask[0], mask[1], mask[2], mask[3],
339) gateway[0], gateway[1], gateway[2], gateway[3]);
340) debug_dhcp_printf("ack time=%ld server=%d.%d.%d.%d",
341) time, server[0], server[1], server[2], server[3]);
342)
343) // check if IP address, mask and gateway match
344) if (!ip_eq(ConfigIp, addr) ||
345) !ip_eq(ConfigMask, mask) || !ip_eq(ConfigGw, gateway)) {
346) // mismatch ---> something is wrong, abort
347) DhcpAbort();
348) return;
349) }
350) // store DHCP server and lease time
351) DhcpActive = 1;
352) ip_cpy(DhcpServer, server);
353) DhcpLeaseTime = time;
354) DhcpLeaseRest = time;
355)
356) // DHCP action finished
357) DhcpInProgress = 0;
358) DhcpRetries = 0;
359) DhcpRetrySecs = 0;
360)
361) // forget XId
362) DhcpHaveXId = 0;
363) DhcpXId = 0;
364) DhcpXIdSecs = 0;
365) }
366)
367) // process a received DHCP packet
368) void DhcpRecv(unsigned char *pData, unsigned short Length) // (extern)
369) {
370) struct DhcpPacket *pDhcpPack;
371) unsigned char *opt_ptr, tag, len;
372) unsigned short opt_len;
373) unsigned char type;
|