source: uKadecot/trunk/uip/apps/dhcpc/dhcpc.c@ 101

Last change on this file since 101 was 101, checked in by coas-nagasima, 9 years ago

TOPPERS/uKadecotのソースコードを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/plain
File size: 10.6 KB
RevLine 
[101]1/*
2 * Copyright (c) 2005, Swedish Institute of Computer Science
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the uIP TCP/IP stack
30 *
31 * @(#)$Id: dhcpc.c 101 2015-06-02 15:37:23Z coas-nagasima $
32 */
33
34#include <stdio.h>
35#include <string.h>
36
37#include "uip.h"
38#include "dhcpc.h"
39#include "timer.h"
40#include "pt.h"
41
42#define STATE_INITIAL 0
43#define STATE_SENDING 1
44#define STATE_OFFER_RECEIVED 2
45#define STATE_CONFIG_RECEIVED 3
46
47#ifdef __RX
48#pragma pack
49#elif _MSC_VER
50#pragma pack(push, 1)
51#endif
52
53struct dhcp_msg {
54 u8_t op, htype, hlen, hops;
55 u8_t xid[4];
56 u16_t secs, flags;
57 u8_t ciaddr[4];
58 u8_t yiaddr[4];
59 u8_t siaddr[4];
60 u8_t giaddr[4];
61 u8_t chaddr[16];
62#ifndef UIP_CONF_DHCP_LIGHT
63 u8_t sname[64];
64 u8_t file[128];
65#endif
66 u8_t options[312];
67};
68
69#ifdef __RX
70#pragma unpack
71#elif _MSC_VER
72#pragma pack(pop)
73#endif
74
75#define BOOTP_BROADCAST 0x8000
76
77#define DHCP_REQUEST 1
78#define DHCP_REPLY 2
79#define DHCP_HTYPE_ETHERNET 1
80#define DHCP_HLEN_ETHERNET 6
81#define DHCP_MSG_LEN 236
82
83#define DHCPC_SERVER_PORT 67
84#define DHCPC_CLIENT_PORT 68
85
86#define DHCPDISCOVER 1
87#define DHCPOFFER 2
88#define DHCPREQUEST 3
89#define DHCPDECLINE 4
90#define DHCPACK 5
91#define DHCPNAK 6
92#define DHCPRELEASE 7
93
94#define DHCP_OPTION_SUBNET_MASK 1
95#define DHCP_OPTION_ROUTER 3
96#define DHCP_OPTION_DNS_SERVER 6
97#define DHCP_OPTION_REQ_IPADDR 50
98#define DHCP_OPTION_LEASE_TIME 51
99#define DHCP_OPTION_MSG_TYPE 53
100#define DHCP_OPTION_SERVER_ID 54
101#define DHCP_OPTION_REQ_LIST 55
102#define DHCP_OPTION_END 255
103
104static const u8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
105static const u8_t magic_cookie[4] = {99, 130, 83, 99};
106/*---------------------------------------------------------------------------*/
107static u8_t *
108add_msg_type(u8_t *optptr, u8_t type)
109{
110 *optptr++ = DHCP_OPTION_MSG_TYPE;
111 *optptr++ = 1;
112 *optptr++ = type;
113 return optptr;
114}
115/*---------------------------------------------------------------------------*/
116static u8_t *
117add_server_id(struct dhcpc_state *s, u8_t *optptr)
118{
119 *optptr++ = DHCP_OPTION_SERVER_ID;
120 *optptr++ = 4;
121 memcpy(optptr, s->serverid, 4);
122 return optptr + 4;
123}
124/*---------------------------------------------------------------------------*/
125static u8_t *
126add_req_ipaddr(struct dhcpc_state *s, u8_t *optptr)
127{
128 *optptr++ = DHCP_OPTION_REQ_IPADDR;
129 *optptr++ = 4;
130 memcpy(optptr, s->ipaddr, 4);
131 return optptr + 4;
132}
133/*---------------------------------------------------------------------------*/
134static u8_t *
135add_req_options(u8_t *optptr)
136{
137 *optptr++ = DHCP_OPTION_REQ_LIST;
138 *optptr++ = 3;
139 *optptr++ = DHCP_OPTION_SUBNET_MASK;
140 *optptr++ = DHCP_OPTION_ROUTER;
141 *optptr++ = DHCP_OPTION_DNS_SERVER;
142 return optptr;
143}
144/*---------------------------------------------------------------------------*/
145static u8_t *
146add_end(u8_t *optptr)
147{
148 *optptr++ = DHCP_OPTION_END;
149 return optptr;
150}
151/*---------------------------------------------------------------------------*/
152static void
153create_msg(struct dhcpc_state *s, struct dhcp_msg *m)
154{
155 m->op = DHCP_REQUEST;
156 m->htype = DHCP_HTYPE_ETHERNET;
157 m->hlen = s->mac_len;
158 m->hops = 0;
159 memcpy(m->xid, xid, sizeof(m->xid));
160 m->secs = 0;
161 m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */
162 /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/
163 memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr));
164 memset(m->yiaddr, 0, sizeof(m->yiaddr));
165 memset(m->siaddr, 0, sizeof(m->siaddr));
166 memset(m->giaddr, 0, sizeof(m->giaddr));
167 memcpy(m->chaddr, s->mac_addr, s->mac_len);
168 memset(&m->chaddr[s->mac_len], 0, sizeof(m->chaddr) - s->mac_len);
169#ifndef UIP_CONF_DHCP_LIGHT
170 memset(m->sname, 0, sizeof(m->sname));
171 memset(m->file, 0, sizeof(m->file));
172#endif
173
174 memcpy(m->options, magic_cookie, sizeof(magic_cookie));
175}
176/*---------------------------------------------------------------------------*/
177static void
178send_discover(struct dhcpc_state *s)
179{
180 u8_t *end;
181 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
182
183 create_msg(s, m);
184
185 end = add_msg_type(&m->options[4], DHCPDISCOVER);
186 end = add_req_options(end);
187 end = add_end(end);
188
189 uip_send(uip_appdata, end - (u8_t *)uip_appdata);
190}
191/*---------------------------------------------------------------------------*/
192static void
193send_request(struct dhcpc_state *s)
194{
195 u8_t *end;
196 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
197
198 create_msg(s, m);
199
200 end = add_msg_type(&m->options[4], DHCPREQUEST);
201 end = add_server_id(s, end);
202 end = add_req_ipaddr(s, end);
203 end = add_end(end);
204
205 uip_send(uip_appdata, end - (u8_t *)uip_appdata);
206}
207/*---------------------------------------------------------------------------*/
208static u8_t
209parse_options(struct dhcpc_state *s, u8_t *optptr, int len)
210{
211 u8_t *end = optptr + len;
212 u8_t type = 0;
213
214 while(optptr < end) {
215 switch(*optptr) {
216 case DHCP_OPTION_SUBNET_MASK:
217 memcpy(s->netmask, optptr + 2, 4);
218 break;
219 case DHCP_OPTION_ROUTER:
220 memcpy(s->default_router, optptr + 2, 4);
221 break;
222 case DHCP_OPTION_DNS_SERVER:
223 memcpy(s->dnsaddr, optptr + 2, 4);
224 break;
225 case DHCP_OPTION_MSG_TYPE:
226 type = *(optptr + 2);
227 break;
228 case DHCP_OPTION_SERVER_ID:
229 memcpy(s->serverid, optptr + 2, 4);
230 break;
231 case DHCP_OPTION_LEASE_TIME:
232 memcpy(s->lease_time, optptr + 2, 4);
233 break;
234 case DHCP_OPTION_END:
235 return type;
236 }
237
238 optptr += optptr[1] + 2;
239 }
240 return type;
241}
242/*---------------------------------------------------------------------------*/
243static u8_t
244parse_msg(struct dhcpc_state *s)
245{
246 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
247
248 if(m->op == DHCP_REPLY &&
249 memcmp(m->xid, xid, sizeof(xid)) == 0 &&
250 memcmp(m->chaddr, s->mac_addr, s->mac_len) == 0) {
251 memcpy(s->ipaddr, m->yiaddr, 4);
252 return parse_options(s, &m->options[4], uip_datalen());
253 }
254 return 0;
255}
256/*---------------------------------------------------------------------------*/
257static
258PT_THREAD(handle_dhcp(struct dhcpc_state *s))
259{
260 int ret;
261 PT_BEGIN(&s->pt);
262
263 /* try_again:*/
264 s->state = STATE_SENDING;
265 s->ticks = 5 * CLOCK_SECOND;
266
267 send_discover(s);
268 timer_set(&s->timer, s->ticks);
269
270 do {
271 PT_WAIT_UNTIL(&s->pt, (ret = uip_newdata() ? 1 : (timer_expired(&s->timer) ? 2 : 0)) != 0);
272
273 if((ret == 1) && parse_msg(s) == DHCPOFFER) {
274 s->state = STATE_OFFER_RECEIVED;
275 break;
276 }
277 if(ret != 2)
278 continue;
279
280 if(s->ticks < CLOCK_SECOND * 60) {
281 s->ticks += CLOCK_SECOND;
282 }
283 timer_set(&s->timer, s->ticks);
284 } while(s->state != STATE_OFFER_RECEIVED);
285
286 s->ticks = CLOCK_SECOND;
287
288 PT_YIELD(&s->pt);
289
290 send_request(s);
291 timer_set(&s->timer, s->ticks);
292
293 do {
294 PT_WAIT_UNTIL(&s->pt, (ret = uip_newdata() ? 1 : (timer_expired(&s->timer) ? 2 : 0)) != 0);
295
296 if((ret == 1) && parse_msg(s) == DHCPACK) {
297 s->state = STATE_CONFIG_RECEIVED;
298 break;
299 }
300 if(ret != 2)
301 continue;
302
303 if(s->ticks <= CLOCK_SECOND * 60) {
304 s->ticks += CLOCK_SECOND;
305 timer_set(&s->timer, s->ticks);
306 } else {
307 PT_RESTART(&s->pt);
308 }
309 } while(s->state != STATE_CONFIG_RECEIVED);
310
311#if 0
312 printf("Got IP address %d.%d.%d.%d\n",
313 uip_ipaddr1(s->ipaddr), uip_ipaddr2(s->ipaddr),
314 uip_ipaddr3(s->ipaddr), uip_ipaddr4(s->ipaddr));
315 printf("Got netmask %d.%d.%d.%d\n",
316 uip_ipaddr1(s->netmask), uip_ipaddr2(s->netmask),
317 uip_ipaddr3(s->netmask), uip_ipaddr4(s->netmask));
318 printf("Got DNS server %d.%d.%d.%d\n",
319 uip_ipaddr1(s->dnsaddr), uip_ipaddr2(s->dnsaddr),
320 uip_ipaddr3(s->dnsaddr), uip_ipaddr4(s->dnsaddr));
321 printf("Got default router %d.%d.%d.%d\n",
322 uip_ipaddr1(s->default_router), uip_ipaddr2(s->default_router),
323 uip_ipaddr3(s->default_router), uip_ipaddr4(s->default_router));
324 printf("Lease expires in %ld seconds\n",
325 ntohs(s->lease_time[0])*65536ul + ntohs(s->lease_time[1]));
326#endif
327
328 dhcpc_configured(s);
329
330 /* timer_stop(&s->timer);*/
331
332 /*
333 * PT_END restarts the thread so we do this instead. Eventually we
334 * should reacquire expired leases here.
335 */
336 while(1) {
337 PT_YIELD(&s->pt);
338 if(s->state == STATE_INITIAL)
339 PT_RESTART(&s->pt);
340 }
341
342 PT_END(&s->pt);
343}
344/*---------------------------------------------------------------------------*/
345struct dhcpc_state *
346dhcpc_init(const void *mac_addr, int mac_len)
347{
348 struct uip_udp_conn *conn;
349 struct dhcpc_state *s;
350 uip_ipaddr_t addr;
351
352 uip_ipaddr(addr, 255,255,255,255);
353 conn = uip_udp_new(&addr, HTONS(DHCPC_SERVER_PORT));
354 if(conn != NULL) {
355 s = &conn->appstate.parblk.dhcpc;
356 s->conn = conn;
357 s->mac_addr = mac_addr;
358 s->mac_len = mac_len;
359
360 s->state = STATE_INITIAL;
361 s->conn->appstate.udp_callback = dhcpc_appcall;
362
363 uip_udp_bind(conn, HTONS(DHCPC_CLIENT_PORT));
364
365 PT_INIT(&s->pt);
366
367 return s;
368 }
369
370 return NULL;
371}
372/*---------------------------------------------------------------------------*/
373void
374dhcpc_appcall(struct uip_udp_conn *uip_udp_conn, int fncd, void *p_parblk)
375{
376 handle_dhcp((struct dhcpc_state *)p_parblk);
377}
378/*---------------------------------------------------------------------------*/
379void
380dhcpc_request(struct dhcpc_state *s)
381{
382 u16_t ipaddr[2];
383
384 s->state = STATE_INITIAL;
385 uip_ipaddr(ipaddr, 0,0,0,0);
386 uip_sethostaddr(ipaddr);
387 uip_udp_conn = s->conn;
388 uip_process(UIP_UDP_TIMER);
389}
390/*---------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.