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

Last change on this file was 262, checked in by coas-nagasima, 7 years ago

uIPを更新
プロジェクトファイルを更新

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-chdr; charset=SHIFT_JIS
File size: 11.0 KB
Line 
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 262 2016-11-18 05:58:30Z coas-nagasima $
32 */
33
34#include <stdio.h>
35#include <string.h>
36
37#include "net/ip/uip.h"
38#include "dhcpc/dhcpc.h"
39#include "sys/timer.h"
40#include "sys/pt.h"
41
42#define STATE_INITIAL 0
43#define STATE_REQUEST 1
44#define STATE_SENDING 2
45#define STATE_OFFER_RECEIVED 3
46#define STATE_CONFIG_RECEIVED 4
47
48#ifdef __RX
49#pragma pack
50#elif _MSC_VER
51#pragma pack(push, 1)
52#endif
53
54struct dhcp_msg {
55 uint8_t op, htype, hlen, hops;
56 uint8_t xid[4];
57 uint16_t secs, flags;
58 uint8_t ciaddr[4];
59 uint8_t yiaddr[4];
60 uint8_t siaddr[4];
61 uint8_t giaddr[4];
62 uint8_t chaddr[16];
63#ifndef UIP_CONF_DHCP_LIGHT
64 uint8_t sname[64];
65 uint8_t file[128];
66#endif
67 uint8_t options[312];
68};
69
70#ifdef __RX
71#pragma unpack
72#elif _MSC_VER
73#pragma pack(pop)
74#endif
75
76#define BOOTP_BROADCAST 0x8000
77
78#define DHCP_REQUEST 1
79#define DHCP_REPLY 2
80#define DHCP_HTYPE_ETHERNET 1
81#define DHCP_HLEN_ETHERNET 6
82#define DHCP_MSG_LEN 236
83
84#define DHCPC_SERVER_PORT 67
85#define DHCPC_CLIENT_PORT 68
86
87#define DHCPDISCOVER 1
88#define DHCPOFFER 2
89#define DHCPREQUEST 3
90#define DHCPDECLINE 4
91#define DHCPACK 5
92#define DHCPNAK 6
93#define DHCPRELEASE 7
94
95#define DHCP_OPTION_SUBNET_MASK 1
96#define DHCP_OPTION_ROUTER 3
97#define DHCP_OPTION_DNS_SERVER 6
98#define DHCP_OPTION_REQ_IPADDR 50
99#define DHCP_OPTION_LEASE_TIME 51
100#define DHCP_OPTION_MSG_TYPE 53
101#define DHCP_OPTION_SERVER_ID 54
102#define DHCP_OPTION_REQ_LIST 55
103#define DHCP_OPTION_END 255
104
105static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
106static const uint8_t magic_cookie[4] = {99, 130, 83, 99};
107/*---------------------------------------------------------------------------*/
108static uint8_t *
109add_msg_type(uint8_t *optptr, uint8_t type)
110{
111 *optptr++ = DHCP_OPTION_MSG_TYPE;
112 *optptr++ = 1;
113 *optptr++ = type;
114 return optptr;
115}
116/*---------------------------------------------------------------------------*/
117static uint8_t *
118add_server_id(struct dhcpc_state *s, uint8_t *optptr)
119{
120 *optptr++ = DHCP_OPTION_SERVER_ID;
121 *optptr++ = 4;
122 memcpy(optptr, s->serverid, 4);
123 return optptr + 4;
124}
125/*---------------------------------------------------------------------------*/
126static uint8_t *
127add_req_ipaddr(struct dhcpc_state *s, uint8_t *optptr)
128{
129 *optptr++ = DHCP_OPTION_REQ_IPADDR;
130 *optptr++ = 4;
131 memcpy(optptr, s->ipaddr, 4);
132 return optptr + 4;
133}
134/*---------------------------------------------------------------------------*/
135static uint8_t *
136add_req_options(uint8_t *optptr)
137{
138 *optptr++ = DHCP_OPTION_REQ_LIST;
139 *optptr++ = 3;
140 *optptr++ = DHCP_OPTION_SUBNET_MASK;
141 *optptr++ = DHCP_OPTION_ROUTER;
142 *optptr++ = DHCP_OPTION_DNS_SERVER;
143 return optptr;
144}
145/*---------------------------------------------------------------------------*/
146static uint8_t *
147add_end(uint8_t *optptr)
148{
149 *optptr++ = DHCP_OPTION_END;
150 return optptr;
151}
152/*---------------------------------------------------------------------------*/
153static void
154create_msg(struct dhcpc_state *s, struct dhcp_msg *m)
155{
156 m->op = DHCP_REQUEST;
157 m->htype = DHCP_HTYPE_ETHERNET;
158 m->hlen = s->mac_len;
159 m->hops = 0;
160 memcpy(m->xid, xid, sizeof(m->xid));
161 m->secs = 0;
162 m->flags = UIP_HTONS(BOOTP_BROADCAST); /* Broadcast bit. */
163 /* uip_ipaddr_copy(&m->ciaddr, &uip_hostaddr);*/
164 memcpy(m->ciaddr, &uip_hostaddr, sizeof(m->ciaddr));
165 memset(m->yiaddr, 0, sizeof(m->yiaddr));
166 memset(m->siaddr, 0, sizeof(m->siaddr));
167 memset(m->giaddr, 0, sizeof(m->giaddr));
168 memcpy(m->chaddr, s->mac_addr, s->mac_len);
169 memset(&m->chaddr[s->mac_len], 0, sizeof(m->chaddr) - s->mac_len);
170#ifndef UIP_CONF_DHCP_LIGHT
171 memset(m->sname, 0, sizeof(m->sname));
172 memset(m->file, 0, sizeof(m->file));
173#endif
174
175 memcpy(m->options, magic_cookie, sizeof(magic_cookie));
176}
177/*---------------------------------------------------------------------------*/
178static void
179send_discover(struct dhcpc_state *s)
180{
181 uint8_t *end;
182 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
183
184 create_msg(s, m);
185
186 end = add_msg_type(&m->options[4], DHCPDISCOVER);
187 end = add_req_options(end);
188 end = add_end(end);
189
190 uip_send(uip_appdata, end - (uint8_t *)uip_appdata);
191}
192/*---------------------------------------------------------------------------*/
193static void
194send_request(struct dhcpc_state *s)
195{
196 uint8_t *end;
197 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
198
199 create_msg(s, m);
200
201 end = add_msg_type(&m->options[4], DHCPREQUEST);
202 end = add_server_id(s, end);
203 end = add_req_ipaddr(s, end);
204 end = add_end(end);
205
206 uip_send(uip_appdata, end - (uint8_t *)uip_appdata);
207}
208/*---------------------------------------------------------------------------*/
209static uint8_t
210parse_options(struct dhcpc_state *s, uint8_t *optptr, int len)
211{
212 uint8_t *end = optptr + len;
213 uint8_t type = 0;
214
215 while(optptr < end) {
216 switch(*optptr) {
217 case DHCP_OPTION_SUBNET_MASK:
218 memcpy(s->netmask, optptr + 2, 4);
219 break;
220 case DHCP_OPTION_ROUTER:
221 memcpy(s->default_router, optptr + 2, 4);
222 break;
223 case DHCP_OPTION_DNS_SERVER:
224 memcpy(s->dnsaddr, optptr + 2, 4);
225 break;
226 case DHCP_OPTION_MSG_TYPE:
227 type = *(optptr + 2);
228 break;
229 case DHCP_OPTION_SERVER_ID:
230 memcpy(s->serverid, optptr + 2, 4);
231 break;
232 case DHCP_OPTION_LEASE_TIME:
233 memcpy(s->lease_time, optptr + 2, 4);
234 break;
235 case DHCP_OPTION_END:
236 return type;
237 }
238
239 optptr += optptr[1] + 2;
240 }
241 return type;
242}
243/*---------------------------------------------------------------------------*/
244static uint8_t
245parse_msg(struct dhcpc_state *s)
246{
247 struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
248
249 if(m->op == DHCP_REPLY &&
250 memcmp(m->xid, xid, sizeof(xid)) == 0 &&
251 memcmp(m->chaddr, s->mac_addr, s->mac_len) == 0) {
252 memcpy(s->ipaddr, m->yiaddr, 4);
253 return parse_options(s, &m->options[4], uip_datalen());
254 }
255 return 0;
256}
257/*---------------------------------------------------------------------------*/
258static
259PT_THREAD(handle_dhcp(struct dhcpc_state *s))
260{
261 int ret;
262 PT_BEGIN(&s->pt);
263
264 if(s->state != STATE_REQUEST)
265 PT_YIELD(&s->pt);
266
267 /* try_again:*/
268 s->state = STATE_SENDING;
269 s->ticks = 5 * CLOCK_SECOND;
270
271 do {
272 printf("send_discover(%d)\n", s->timer);
273 send_discover(s);
274 timer_set(&s->timer, s->ticks);
275
276 PT_WAIT_UNTIL(&s->pt, (ret = uip_newdata() ? 1 : (timer_expired(&s->timer) ? 2 : 0)) != 0);
277
278 if((ret == 1) && parse_msg(s) == DHCPOFFER) {
279 s->state = STATE_OFFER_RECEIVED;
280 break;
281 }
282 if(ret != 2)
283 continue;
284
285 if(s->ticks < CLOCK_SECOND * 60) {
286 s->ticks += CLOCK_SECOND;
287 }
288 timer_set(&s->timer, s->ticks);
289 } while(s->state != STATE_OFFER_RECEIVED);
290
291 s->ticks = CLOCK_SECOND;
292
293 PT_YIELD(&s->pt);
294
295 do {
296 printf("send_request(%d)\n", s->timer);
297 send_request(s);
298 timer_set(&s->timer, s->ticks);
299
300 PT_WAIT_UNTIL(&s->pt, (ret = uip_newdata() ? 1 : (timer_expired(&s->timer) ? 2 : 0)) != 0);
301
302 if((ret == 1) && parse_msg(s) == DHCPACK) {
303 s->state = STATE_CONFIG_RECEIVED;
304 break;
305 }
306 if(ret != 2)
307 continue;
308
309 if(s->ticks <= CLOCK_SECOND * 60) {
310 s->ticks += CLOCK_SECOND;
311 timer_set(&s->timer, s->ticks);
312 } else {
313 PT_RESTART(&s->pt);
314 }
315 } while(s->state != STATE_CONFIG_RECEIVED);
316
317#if 0
318 printf("Got IP address %d.%d.%d.%d\n",
319 uip_ipaddr1(s->ipaddr), uip_ipaddr2(s->ipaddr),
320 uip_ipaddr3(s->ipaddr), uip_ipaddr4(s->ipaddr));
321 printf("Got netmask %d.%d.%d.%d\n",
322 uip_ipaddr1(s->netmask), uip_ipaddr2(s->netmask),
323 uip_ipaddr3(s->netmask), uip_ipaddr4(s->netmask));
324 printf("Got DNS server %d.%d.%d.%d\n",
325 uip_ipaddr1(s->dnsaddr), uip_ipaddr2(s->dnsaddr),
326 uip_ipaddr3(s->dnsaddr), uip_ipaddr4(s->dnsaddr));
327 printf("Got default router %d.%d.%d.%d\n",
328 uip_ipaddr1(s->default_router), uip_ipaddr2(s->default_router),
329 uip_ipaddr3(s->default_router), uip_ipaddr4(s->default_router));
330 printf("Lease expires in %ld seconds\n",
331 uip_ntohs(s->lease_time[0])*65536ul + uip_ntohs(s->lease_time[1]));
332#endif
333
334 dhcpc_configured(s);
335
336 /* timer_stop(&s->timer);*/
337
338 /*
339 * PT_END restarts the thread so we do this instead. Eventually we
340 * should reacquire expired leases here.
341 */
342 while(1) {
343 PT_YIELD(&s->pt);
344 if(s->state == STATE_INITIAL)
345 PT_RESTART(&s->pt);
346 }
347
348 PT_END(&s->pt);
349}
350/*---------------------------------------------------------------------------*/
351struct dhcpc_state *
352dhcpc_init(const void *mac_addr, int mac_len)
353{
354 struct uip_udp_conn *conn;
355 struct dhcpc_state *s;
356 uip_ipaddr_t addr;
357
358 uip_ipaddr(&addr, 255,255,255,255);
359 conn = uip_udp_new(&addr, UIP_HTONS(DHCPC_SERVER_PORT));
360 if(conn != NULL) {
361 s = &conn->appstate.parblk.dhcpc;
362 s->conn = conn;
363 s->mac_addr = mac_addr;
364 s->mac_len = mac_len;
365
366 s->state = STATE_INITIAL;
367 s->conn->appstate.udp_callback = dhcpc_appcall;
368
369 uip_udp_bind(conn, UIP_HTONS(DHCPC_CLIENT_PORT));
370
371 PT_INIT(&s->pt);
372
373 return s;
374 }
375
376 return NULL;
377}
378/*---------------------------------------------------------------------------*/
379void
380dhcpc_appcall(struct uip_udp_conn *uip_udp_conn, int fncd, void *p_parblk)
381{
382 handle_dhcp((struct dhcpc_state *)p_parblk);
383}
384/*---------------------------------------------------------------------------*/
385void
386dhcpc_request(struct dhcpc_state *s)
387{
388 uip_ipaddr_t ipaddr;
389
390 s->state = STATE_REQUEST;
391 uip_ipaddr(&ipaddr, 0,0,0,0);
392 uip_sethostaddr(&ipaddr);
393 uip_udp_conn = s->conn;
394 uip_process(UIP_UDP_TIMER);
395}
396/*---------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.