38 #include "contiki-net.h"
39 #include "net/dhcpc.h"
41 #define STATE_INITIAL 0
42 #define STATE_SENDING 1
43 #define STATE_OFFER_RECEIVED 2
44 #define STATE_CONFIG_RECEIVED 3
46 static struct dhcpc_state s;
49 u8_t op, htype, hlen, hops;
57 #ifndef UIP_CONF_DHCP_LIGHT
64 #define BOOTP_BROADCAST 0x8000
66 #define DHCP_REQUEST 1
68 #define DHCP_HTYPE_ETHERNET 1
69 #define DHCP_HLEN_ETHERNET 6
70 #define DHCP_MSG_LEN 236
72 #define DHCPC_SERVER_PORT 67
73 #define DHCPC_CLIENT_PORT 68
75 #define DHCPDISCOVER 1
83 #define DHCP_OPTION_SUBNET_MASK 1
84 #define DHCP_OPTION_ROUTER 3
85 #define DHCP_OPTION_DNS_SERVER 6
86 #define DHCP_OPTION_REQ_IPADDR 50
87 #define DHCP_OPTION_LEASE_TIME 51
88 #define DHCP_OPTION_MSG_TYPE 53
89 #define DHCP_OPTION_SERVER_ID 54
90 #define DHCP_OPTION_REQ_LIST 55
91 #define DHCP_OPTION_END 255
94 static const u8_t magic_cookie[4] = {99, 130, 83, 99};
97 add_msg_type(u8_t *optptr, u8_t type)
99 *optptr++ = DHCP_OPTION_MSG_TYPE;
106 add_server_id(u8_t *optptr)
108 *optptr++ = DHCP_OPTION_SERVER_ID;
110 memcpy(optptr, s.serverid, 4);
115 add_req_ipaddr(u8_t *optptr)
117 *optptr++ = DHCP_OPTION_REQ_IPADDR;
119 memcpy(optptr, s.ipaddr.u16, 4);
124 add_req_options(u8_t *optptr)
126 *optptr++ = DHCP_OPTION_REQ_LIST;
128 *optptr++ = DHCP_OPTION_SUBNET_MASK;
129 *optptr++ = DHCP_OPTION_ROUTER;
130 *optptr++ = DHCP_OPTION_DNS_SERVER;
135 add_end(u8_t *optptr)
137 *optptr++ = DHCP_OPTION_END;
144 m->op = DHCP_REQUEST;
145 m->htype = DHCP_HTYPE_ETHERNET;
148 memcpy(m->xid, &xid,
sizeof(m->xid));
152 memcpy(m->ciaddr, uip_hostaddr.u16,
sizeof(m->ciaddr));
153 memset(m->yiaddr, 0,
sizeof(m->yiaddr));
154 memset(m->siaddr, 0,
sizeof(m->siaddr));
155 memset(m->giaddr, 0,
sizeof(m->giaddr));
156 memcpy(m->chaddr, s.mac_addr, s.mac_len);
157 memset(&m->chaddr[s.mac_len], 0,
sizeof(m->chaddr) - s.mac_len);
158 #ifndef UIP_CONF_DHCP_LIGHT
159 memset(m->sname, 0,
sizeof(m->sname));
160 memset(m->file, 0,
sizeof(m->file));
163 memcpy(m->options, magic_cookie,
sizeof(magic_cookie));
170 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
174 end = add_msg_type(&m->options[4], DHCPDISCOVER);
175 end = add_req_options(end);
185 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
189 end = add_msg_type(&m->options[4], DHCPREQUEST);
190 end = add_server_id(end);
191 end = add_req_ipaddr(end);
198 parse_options(u8_t *optptr,
int len)
200 u8_t *end = optptr + len;
203 while(optptr < end) {
205 case DHCP_OPTION_SUBNET_MASK:
206 memcpy(s.netmask.u16, optptr + 2, 4);
208 case DHCP_OPTION_ROUTER:
209 memcpy(s.default_router.u16, optptr + 2, 4);
211 case DHCP_OPTION_DNS_SERVER:
212 memcpy(s.dnsaddr.u16, optptr + 2, 4);
214 case DHCP_OPTION_MSG_TYPE:
215 type = *(optptr + 2);
217 case DHCP_OPTION_SERVER_ID:
218 memcpy(s.serverid, optptr + 2, 4);
220 case DHCP_OPTION_LEASE_TIME:
221 memcpy(s.lease_time, optptr + 2, 4);
223 case DHCP_OPTION_END:
227 optptr += optptr[1] + 2;
235 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
237 if(m->op == DHCP_REPLY &&
238 memcmp(m->xid, &xid,
sizeof(xid)) == 0 &&
239 memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) {
240 memcpy(s.ipaddr.u16, m->yiaddr, 4);
241 return parse_options(&m->options[4],
uip_datalen());
252 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
253 u8_t *optptr = &m->options[4];
256 if(m->op == DHCP_REPLY &&
257 memcmp(m->xid, &xid,
sizeof(xid)) == 0 &&
258 memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) {
259 while(optptr < end) {
260 if(*optptr == DHCP_OPTION_MSG_TYPE) {
261 return *(optptr + 2);
262 }
else if (*optptr == DHCP_OPTION_END) {
265 optptr += optptr[1] + 2;
272 PT_THREAD(handle_dhcp(process_event_t ev,
void *data))
280 s.state = STATE_SENDING;
293 s.state = STATE_OFFER_RECEIVED;
317 s.state = STATE_CONFIG_RECEIVED;
327 }
while(s.state != STATE_CONFIG_RECEIVED);
334 printf(
"Got default router %d.%d.%d.%d\n",
336 printf(
"Lease expires in %ld seconds\n",
337 uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]));
340 dhcpc_configured(&s);
342 #define MAX_TICKS (~((clock_time_t)0) / 2)
343 #define MAX_TICKS32 (~((u32_t)0))
344 #define IMIN(a, b) ((a) < (b) ? (a) : (b))
346 if((uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]))*
CLOCK_SECOND/2
348 s.ticks = (uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1])
351 s.ticks = MAX_TICKS32;
355 ticks = IMIN(s.ticks, MAX_TICKS);
361 if((uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1]))*
CLOCK_SECOND/2
363 s.ticks = (uip_ntohs(s.lease_time[0])*65536ul + uip_ntohs(s.lease_time[1])
366 s.ticks = MAX_TICKS32;
377 ticks = IMIN(s.ticks / 2, MAX_TICKS);
392 dhcpc_unconfigured(&s);
399 dhcpc_init(
const void *mac_addr,
int mac_len)
403 s.mac_addr = mac_addr;
406 s.state = STATE_INITIAL;
416 dhcpc_appcall(process_event_t ev,
void *data)
418 if(ev ==
tcpip_event || ev == PROCESS_EVENT_TIMER) {
419 handle_dhcp(ev, data);
428 if(s.state == STATE_INITIAL) {
431 handle_dhcp(PROCESS_EVENT_NONE,
NULL);