39 #include "contiki-net.h"
43 uint8_t op, htype, hlen, hops;
51 #ifndef UIP_CONF_DHCP_LIGHT
58 #define BOOTP_BROADCAST 0x8000
60 #define DHCP_REQUEST 1
62 #define DHCP_HTYPE_ETHERNET 1
63 #define DHCP_HLEN_ETHERNET 6
64 #define DHCP_MSG_LEN 236
66 #define DHCPS_SERVER_PORT 67
67 #define DHCPS_CLIENT_PORT 68
69 #define DHCPDISCOVER 1
78 #define DHCP_OPTION_SUBNET_MASK 1
79 #define DHCP_OPTION_ROUTER 3
80 #define DHCP_OPTION_DNS_SERVER 6
81 #define DHCP_OPTION_REQ_IPADDR 50
82 #define DHCP_OPTION_LEASE_TIME 51
83 #define DHCP_OPTION_MSG_TYPE 53
84 #define DHCP_OPTION_SERVER_ID 54
85 #define DHCP_OPTION_REQ_LIST 55
86 #define DHCP_OPTION_END 255
90 #define LEASE_FLAGS_ALLOCATED 0x01
91 #define LEASE_FLAGS_VALID 0x02
95 static const struct dhcps_config *config;
99 find_option(uint8_t option)
101 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
102 uint8_t *optptr = &m->options[4];
104 while(optptr < end && *optptr != DHCP_OPTION_END) {
105 if(*optptr == option) {
108 optptr += optptr[1] + 2;
113 static const uint8_t magic_cookie[4] = {99, 130, 83, 99};
118 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
119 return memcmp(m->options, magic_cookie, 4) == 0;
123 static struct dhcps_client_lease *
124 lookup_lease_mac(
const uint8_t *chaddr, uint8_t hlen)
126 struct dhcps_client_lease *lease = config->leases;
127 struct dhcps_client_lease *end = config->leases + config->num_leases;
128 while(lease != end) {
129 if (lease->flags & LEASE_FLAGS_VALID
130 && memcmp(lease->chaddr, chaddr, hlen) == 0) {
138 static struct dhcps_client_lease *
141 struct dhcps_client_lease *lease = config->leases;
142 struct dhcps_client_lease *end = config->leases + config->num_leases;
143 while(lease != end) {
152 static struct dhcps_client_lease *
153 find_free_lease(
void)
155 struct dhcps_client_lease *found =
NULL;
156 struct dhcps_client_lease *lease = config->leases;
157 struct dhcps_client_lease *end = config->leases + config->num_leases;
158 while(lease != end) {
159 if (!(lease->flags & LEASE_FLAGS_VALID))
return lease;
160 if (!(lease->flags & LEASE_FLAGS_ALLOCATED)) found = lease;
166 struct dhcps_client_lease *
167 init_lease(
struct dhcps_client_lease *lease,
168 const uint8_t *chaddr, uint8_t hlen)
171 memcpy(lease->chaddr, chaddr, hlen);
172 lease->flags = LEASE_FLAGS_VALID;
178 static struct dhcps_client_lease *
181 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
182 struct dhcps_client_lease *lease;
183 lease = lookup_lease_mac(m->chaddr, m->hlen);
189 opt = find_option(DHCP_OPTION_REQ_IPADDR);
190 if (opt && (lease = lookup_lease_ip((
uip_ipaddr_t*)&opt[2]))
191 && !(lease->flags & LEASE_FLAGS_ALLOCATED)) {
192 return init_lease(lease, m->chaddr,m->hlen);
195 lease = find_free_lease();
197 return init_lease(lease, m->chaddr,m->hlen);
202 static struct dhcps_client_lease *
205 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
206 struct dhcps_client_lease *lease;
207 lease = lookup_lease_mac(m->chaddr, m->hlen);
210 opt = find_option(DHCP_OPTION_REQ_IPADDR);
211 if (!(opt && (lease = lookup_lease_ip((
uip_ipaddr_t*)&opt[2]))
212 && !(lease->flags & LEASE_FLAGS_ALLOCATED))) {
216 lease->lease_end = clock_seconds()+config->default_lease_time;
217 lease->flags |= LEASE_FLAGS_ALLOCATED;
221 static struct dhcps_client_lease *
224 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
225 struct dhcps_client_lease *lease;
226 lease = lookup_lease_mac(m->chaddr, m->hlen);
230 lease->flags &= ~LEASE_FLAGS_ALLOCATED;
236 add_msg_type(uint8_t *optptr, uint8_t type)
238 *optptr++ = DHCP_OPTION_MSG_TYPE;
245 add_server_id(uint8_t *optptr)
247 *optptr++ = DHCP_OPTION_SERVER_ID;
249 memcpy(optptr, &uip_hostaddr, 4);
254 add_lease_time(uint8_t *optptr)
257 *optptr++ = DHCP_OPTION_LEASE_TIME;
259 lt = UIP_HTONL(config->default_lease_time);
260 memcpy(optptr, <, 4);
266 add_end(uint8_t *optptr)
268 *optptr++ = DHCP_OPTION_END;
273 add_config(uint8_t *optptr)
275 if (config->flags & DHCP_CONF_NETMASK) {
276 *optptr++ = DHCP_OPTION_SUBNET_MASK;
278 memcpy(optptr, &config->netmask, 4);
281 if (config->flags & DHCP_CONF_DNSADDR) {
282 *optptr++ = DHCP_OPTION_DNS_SERVER;
284 memcpy(optptr, &config->dnsaddr, 4);
287 if (config->flags & DHCP_CONF_DEFAULT_ROUTER) {
288 *optptr++ = DHCP_OPTION_ROUTER;
290 memcpy(optptr, &config->default_router, 4);
305 memcpy(m->siaddr, &uip_hostaddr, 4);
308 memcpy(m->options, magic_cookie,
sizeof(magic_cookie));
316 send_offer(
struct uip_udp_conn *conn,
struct dhcps_client_lease *lease)
319 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
322 memcpy(&m->yiaddr, &lease->ipaddr,4);
324 end = add_msg_type(&m->options[4], DHCPOFFER);
325 end = add_server_id(end);
326 end = add_lease_time(end);
327 end = add_config(end);
334 send_ack(
struct uip_udp_conn *conn,
struct dhcps_client_lease *lease)
338 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
341 memcpy(&m->yiaddr, &lease->ipaddr,4);
343 end = add_msg_type(&m->options[4], DHCPACK);
344 end = add_server_id(end);
345 end = add_lease_time(end);
346 end = add_config(end);
348 memcpy(&ciaddr, &lease->ipaddr,4);
357 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
360 memset(&m->yiaddr, 0, 4);
362 end = add_msg_type(&m->options[4], DHCPNAK);
363 end = add_server_id(end);
372 PROCESS(dhcp_server_process,
"DHCP server");
379 static struct dhcps_client_lease *lease;
381 printf(
"DHCP server starting\n");
385 if (!conn)
goto exit;
387 if (!send_conn)
goto exit;
395 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
396 struct uip_udpip_hdr *header = (
struct uip_udpip_hdr *)&uip_buf[
UIP_LLH_LEN];
398 if (m->op == DHCP_REQUEST && check_cookie() && m->hlen <= MAX_HLEN) {
399 uint8_t *opt = find_option(DHCP_OPTION_MSG_TYPE);
401 uint8_t mtype = opt[2];
402 if (opt[2] == DHCPDISCOVER) {
403 printf(
"Discover\n");
404 lease = choose_address();
406 lease->lease_end = clock_seconds()+config->default_lease_time;
409 send_offer(conn,lease);
412 uint8_t *opt = find_option(DHCP_OPTION_SERVER_ID);
414 if (mtype == DHCPREQUEST) {
416 lease = allocate_address();
420 send_nack(send_conn);
422 send_ack(send_conn,lease);
424 }
else if (mtype == DHCPRELEASE) {
427 }
else if (mtype == DHCPDECLINE) {
429 }
else if (mtype == DHCPINFORM) {
442 printf(
"DHCP server exiting\n");
447 dhcps_init(
const struct dhcps_config *conf)