?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

Line No. Rev Author Line
1 6 kaklik /*! \file dhcp.c \brief DHCP Protocol Library. */
2 //*****************************************************************************
3 //
4 // File Name : 'dhcp.c'
5 // Title : DHCP Protocol Library
6 // Author : Pascal Stang
7 // Created : 9/17/2005
8 // Revised : 9/17/2005
9 // Version : 0.1
10 // Target MCU : Atmel AVR series
11 // Editor Tabs : 4
12 //
13 //*****************************************************************************
14  
15 #include "global.h"
16 #include "net.h"
17 #include "nic.h"
18 #include "ip.h"
19 #include "netstack.h"
20  
21 #include "dhcp.h"
22  
23 #include "rprintf.h"
24  
25 // global variables
26 uint32_t DhcpServerIP; ///< IP address of the DHCP server that offered lease
27 uint32_t DhcpTransactID; ///< Unique transaction ID that identifies DHCP request/replies
28 uint32_t DhcpLeaseTime; ///< Number of seconds left in DHCP lease
29  
30 void dhcpInit(void)
31 {
32 uint8_t macaddr[6];
33  
34 // get interface mac address
35 nicGetMacAddress(macaddr);
36 // set transaction ID based on mac address
37 DhcpTransactID = *((uint32_t*)&macaddr);
38 // reset lease time
39 DhcpLeaseTime = 0;
40 }
41  
42 void dhcpIn(unsigned int len, struct netDhcpHeader* packet)
43 {
44 uint8_t msgtype;
45 uint32_t sid;
46 uint8_t* optptr;
47 uint32_t val;
48 uint32_t netmask;
49 uint32_t gateway;
50  
51 #if NET_DEBUG >= 3
52 dhcpPrintHeader(packet);
53 #endif
54  
55 // check that this is a reply, and for me
56 if((packet->bootp.op != BOOTP_OP_BOOTREPLY) || (packet->bootp.xid != DhcpTransactID))
57 return;
58  
59 // process incoming packet
60 // check reply type
61 dhcpGetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &msgtype);
62 #if NET_DEBUG >= 2
63 rprintf("DHCP: Received msgtype = %d\r\n", msgtype);
64 #endif
65  
66 if(msgtype == DHCP_MSG_DHCPOFFER)
67 {
68 // get DHCP server ID
69 dhcpGetOption(packet->options, DHCP_OPT_SERVERID, 4, &sid);
70 #ifdef DHCP_DEBUG
71 rprintfProgStrM("DHCP: Got offer from server "); netPrintIPAddr(htonl(sid)); rprintfCRLF();
72 #endif
73  
74 // build DHCP request (on top of this reply)
75 packet->bootp.op = BOOTP_OP_BOOTREQUEST; // request type
76 // set operation
77 val = DHCP_MSG_DHCPREQUEST;
78 optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
79 // set the server ID
80 optptr = dhcpSetOption(optptr, DHCP_OPT_SERVERID, 4, &sid);
81 // request the IP previously offered
82 optptr = dhcpSetOption(optptr, DHCP_OPT_REQUESTEDIP, 4, &packet->bootp.yiaddr);
83 // request additional information
84 ((uint8_t*)&val)[0] = DHCP_OPT_NETMASK;
85 ((uint8_t*)&val)[1] = DHCP_OPT_ROUTERS;
86 ((uint8_t*)&val)[2] = DHCP_OPT_DNSSERVERS;
87 ((uint8_t*)&val)[3] = DHCP_OPT_DOMAINNAME;
88 optptr = dhcpSetOption(optptr, DHCP_OPT_PARAMREQLIST, 4, &val);
89  
90 #ifdef DHCP_DEBUG
91 rprintfProgStrM("DHCP: Sending request in response to offer\r\n");
92 #endif
93 // send DHCP request
94 DhcpServerIP = htonl(sid);
95 udpSend(DhcpServerIP, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+6+6+6+1, (uint8_t*)packet);
96  
97 }
98 else if(msgtype == DHCP_MSG_DHCPACK)
99 {
100 // get netmask
101 dhcpGetOption(packet->options, DHCP_OPT_NETMASK, 4, &val);
102 netmask = htonl(val);
103 // get gateway
104 dhcpGetOption(packet->options, DHCP_OPT_ROUTERS, 4, &val);
105 gateway = htonl(val);
106 // get gateway
107 dhcpGetOption(packet->options, DHCP_OPT_LEASETIME, 4, &val);
108 DhcpLeaseTime = htonl(val);
109  
110 // assign new network info
111 ipSetConfig(htonl(packet->bootp.yiaddr), netmask, gateway);
112  
113 #ifdef DHCP_DEBUG
114 rprintf("DHCP: Got request ACK, bind complete\r\n");
115 //debugPrintHexTable(len-DHCP_HEADER_LEN, (packet->options));
116 // print info
117 ipPrintConfig(ipGetConfig());
118 rprintfProgStrM("LeaseTm : "); rprintfNum(10,8,FALSE,' ',DhcpLeaseTime); rprintfCRLF();
119 #endif
120 }
121 }
122  
123 void dhcpRequest(void)
124 {
125 struct netDhcpHeader* packet;
126 uint32_t val;
127  
128 packet = (struct netDhcpHeader*)&netstackGetBuffer()[ETH_HEADER_LEN+IP_HEADER_LEN+UDP_HEADER_LEN];
129  
130 // build BOOTP/DHCP header
131 packet->bootp.op = BOOTP_OP_BOOTREQUEST; // request type
132 packet->bootp.htype = BOOTP_HTYPE_ETHERNET;
133 packet->bootp.hlen = BOOTP_HLEN_ETHERNET;
134 packet->bootp.ciaddr = htonl(ipGetConfig()->ip);
135 packet->bootp.yiaddr = HTONL(0l);
136 packet->bootp.siaddr = HTONL(0l);
137 packet->bootp.giaddr = HTONL(0l);
138 nicGetMacAddress(&packet->bootp.chaddr[0]); // fill client hardware address
139 packet->bootp.xid = DhcpTransactID;
140 packet->bootp.flags = HTONS(1);
141  
142 // build DHCP request
143 // begin with magic cookie
144 packet->cookie = 0x63538263;
145 // set operation
146 val = DHCP_MSG_DHCPDISCOVER;
147 dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
148  
149 #ifdef DHCP_DEBUG
150 rprintfProgStrM("DHCP: Sending Query\r\n");
151 //dhcpPrintHeader(packet);
152 #endif
153  
154 // send request
155 udpSend(0xFFFFFFFF, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+1, (uint8_t*)packet);
156 }
157  
158 void dhcpRelease(void)
159 {
160 struct netDhcpHeader* packet;
161 uint32_t val;
162 uint8_t* optptr;
163  
164 packet = (struct netDhcpHeader*)&netstackGetBuffer()[ETH_HEADER_LEN+IP_HEADER_LEN+UDP_HEADER_LEN];
165  
166 // build BOOTP/DHCP header
167 packet->bootp.op = BOOTP_OP_BOOTREQUEST; // request type
168 packet->bootp.htype = BOOTP_HTYPE_ETHERNET;
169 packet->bootp.hlen = BOOTP_HLEN_ETHERNET;
170 packet->bootp.ciaddr = htonl(ipGetConfig()->ip);
171 packet->bootp.yiaddr = HTONL(0l);
172 packet->bootp.siaddr = HTONL(0l);
173 packet->bootp.giaddr = HTONL(0l);
174 nicGetMacAddress(&packet->bootp.chaddr[0]); // fill client hardware address
175 packet->bootp.xid = DhcpTransactID; // set trans ID (use part of MAC address)
176 packet->bootp.flags = HTONS(1);
177  
178 // build DHCP request
179 // begin with magic cookie
180 packet->cookie = 0x63538263;
181 // set operation
182 val = DHCP_MSG_DHCPRELEASE;
183 optptr = dhcpSetOption(packet->options, DHCP_OPT_DHCPMSGTYPE, 1, &val);
184 // set the server ID
185 val = htonl(DhcpServerIP);
186 optptr = dhcpSetOption(optptr, DHCP_OPT_SERVERID, 4, &val);
187 // request the IP previously offered
188 optptr = dhcpSetOption(optptr, DHCP_OPT_REQUESTEDIP, 4, &packet->bootp.ciaddr);
189  
190 #ifdef DHCP_DEBUG
191 rprintfProgStrM("DHCP: Sending Release to "); netPrintIPAddr(DhcpServerIP); rprintfCRLF();
192 //dhcpPrintHeader(packet);
193 #endif
194  
195 // send release
196 udpSend(DhcpServerIP, DHCP_UDP_SERVER_PORT, DHCP_HEADER_LEN+3+6+6+1, (uint8_t*)packet);
197  
198 // deconfigure ip addressing
199 ipSetConfig(0,0,0);
200 DhcpLeaseTime = 0;
201 }
202  
203 void dhcpTimer(void)
204 {
205 // this function to be called once per second
206  
207 // decrement lease time
208 if(DhcpLeaseTime)
209 DhcpLeaseTime--;
210 }
211  
212 uint8_t dhcpGetOption(uint8_t* options, uint8_t optcode, uint8_t optlen, void* optvalptr)
213 {
214 uint8_t i;
215  
216 // parse for desired option
217 for (;;)
218 {
219 // skip pad characters
220 if(*options == DHCP_OPT_PAD)
221 options++;
222 // break if end reached
223 else if(*options == DHCP_OPT_END)
224 break;
225 // check for desired option
226 else if(*options == optcode)
227 {
228 // found desired option
229 // limit size to actual option length
230 optlen = MIN(optlen, *(options+1));
231 //if(*(options+1) < optlen)
232 // optlen = *(options+1);
233  
234 // copy contents of option
235 for(i=0; i<optlen; i++)
236 *(((uint8_t*)optvalptr)+i) = *(options+i+2);
237 // return length of option
238 return *(options+1);
239 }
240 else
241 {
242 // skip to next option
243 options++;
244 options+=*options;
245 options++;
246 }
247 }
248 // failed to find desired option
249 return 0;
250 }
251  
252  
253 uint8_t* dhcpSetOption(uint8_t* options, uint8_t optcode, uint8_t optlen, void* optvalptr)
254 {
255 // use current options address as write point
256  
257 // set optcode
258 *options++ = optcode;
259 // set optlen
260 *options++ = optlen;
261 // copy in argument/data
262 while(optlen--)
263 {
264 *options++ = *(uint8_t*)optvalptr++;
265 }
266 // write end marker
267 *options = DHCP_OPT_END;
268  
269 // return address of end marker, to be used as a future write point
270 return options;
271 }
272  
273  
274 #ifdef DHCP_DEBUG_PRINT
275 void dhcpPrintHeader(struct netDhcpHeader* packet)
276 {
277 rprintfProgStrM("DHCP Packet:\r\n");
278 // print op
279 rprintfProgStrM("Op : ");
280 switch(packet->bootp.op)
281 {
282 case BOOTP_OP_BOOTREQUEST: rprintfProgStrM("BOOTREQUEST"); break;
283 case BOOTP_OP_BOOTREPLY: rprintfProgStrM("BOOTREPLY"); break;
284 default: rprintfProgStrM("UNKNOWN"); break;
285 }
286 rprintfCRLF();
287 // print transaction ID
288 rprintfProgStrM("XID : 0x"); rprintfu32(packet->bootp.xid); rprintfCRLF();
289 // print client IP address
290 rprintfProgStrM("ClIpAddr: "); netPrintIPAddr(htonl(packet->bootp.ciaddr)); rprintfCRLF();
291 // print 'your' IP address
292 rprintfProgStrM("YrIpAddr: "); netPrintIPAddr(htonl(packet->bootp.yiaddr)); rprintfCRLF();
293 // print server IP address
294 rprintfProgStrM("SvIpAddr: "); netPrintIPAddr(htonl(packet->bootp.siaddr)); rprintfCRLF();
295 // print gateway IP address
296 rprintfProgStrM("GwIpAddr: "); netPrintIPAddr(htonl(packet->bootp.giaddr)); rprintfCRLF();
297 // print client hardware address
298 rprintfProgStrM("ClHwAddr: "); netPrintEthAddr((struct netEthAddr*)packet->bootp.chaddr); rprintfCRLF();
299 }
300 #endif
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3