38 #include "contiki-net.h" 42 uint8_t op, htype, hlen, hops;
50 #ifndef UIP_CONF_DHCP_LIGHT 64 #define PRINTD(FORMAT, args...) do {} while (0) 66 #define PRINTD(FORMAT, args...) printf("%s" FORMAT, "[DHCPS] ", ##args) 69 #define BOOTP_BROADCAST 0x8000 71 #define DHCP_REQUEST 1 73 #define DHCP_HTYPE_ETHERNET 1 74 #define DHCP_HLEN_ETHERNET 6 75 #define DHCP_MSG_LEN 236 77 #define DHCPS_SERVER_PORT 67 78 #define DHCPS_CLIENT_PORT 68 80 #define DHCPDISCOVER 1 89 #define DHCP_OPTION_SUBNET_MASK 1 90 #define DHCP_OPTION_ROUTER 3 91 #define DHCP_OPTION_DNS_SERVER 6 92 #define DHCP_OPTION_REQ_IPADDR 50 93 #define DHCP_OPTION_LEASE_TIME 51 94 #define DHCP_OPTION_MSG_TYPE 53 95 #define DHCP_OPTION_SERVER_ID 54 96 #define DHCP_OPTION_REQ_LIST 55 97 #define DHCP_OPTION_END 255 101 #define LEASE_FLAGS_ALLOCATED 0x01 102 #define LEASE_FLAGS_VALID 0x02 106 static const struct dhcps_config *config;
110 find_option(uint8_t option)
112 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
113 uint8_t *optptr = &m->options[4];
115 while(optptr < end && *optptr != DHCP_OPTION_END) {
116 if(*optptr == option) {
119 optptr += optptr[1] + 2;
124 static const uint8_t magic_cookie[4] = {99, 130, 83, 99};
129 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
130 return memcmp(m->options, magic_cookie, 4) == 0;
134 static struct dhcps_client_lease *
135 lookup_lease_mac(
const uint8_t *chaddr, uint8_t hlen)
137 struct dhcps_client_lease *lease = config->leases;
138 struct dhcps_client_lease *end = config->leases + config->num_leases;
139 while(lease != end) {
140 if ((lease->flags & LEASE_FLAGS_VALID)
141 && memcmp(lease->chaddr, chaddr, hlen) == 0) {
149 static struct dhcps_client_lease *
152 struct dhcps_client_lease *lease = config->leases;
153 struct dhcps_client_lease *end = config->leases + config->num_leases;
154 while(lease != end) {
155 if (uip_ipaddr_cmp(&lease->ipaddr, ip)) {
163 static struct dhcps_client_lease *
164 find_free_lease(
void)
166 struct dhcps_client_lease *found = NULL;
167 struct dhcps_client_lease *lease = config->leases;
168 struct dhcps_client_lease *end = config->leases + config->num_leases;
169 while(lease != end) {
170 if (!(lease->flags & LEASE_FLAGS_VALID))
return lease;
171 if (!(lease->flags & LEASE_FLAGS_ALLOCATED)) found = lease;
177 struct dhcps_client_lease *
178 init_lease(
struct dhcps_client_lease *lease,
179 const uint8_t *chaddr, uint8_t hlen)
182 memcpy(lease->chaddr, chaddr, hlen);
183 lease->flags = LEASE_FLAGS_VALID;
189 static struct dhcps_client_lease *
192 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
193 struct dhcps_client_lease *lease;
194 lease = lookup_lease_mac(m->chaddr, m->hlen);
200 opt = find_option(DHCP_OPTION_REQ_IPADDR);
201 if (opt && (lease = lookup_lease_ip((
uip_ipaddr_t*)&opt[2]))
202 && !(lease->flags & LEASE_FLAGS_ALLOCATED)) {
203 return init_lease(lease, m->chaddr,m->hlen);
206 lease = find_free_lease();
208 return init_lease(lease, m->chaddr,m->hlen);
213 static struct dhcps_client_lease *
216 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
217 struct dhcps_client_lease *lease;
218 lease = lookup_lease_mac(m->chaddr, m->hlen);
221 opt = find_option(DHCP_OPTION_REQ_IPADDR);
222 if (!(opt && (lease = lookup_lease_ip((
uip_ipaddr_t*)&opt[2]))
223 && !(lease->flags & LEASE_FLAGS_ALLOCATED))) {
227 lease->lease_end =
clock_seconds()+config->default_lease_time;
228 lease->flags |= LEASE_FLAGS_ALLOCATED;
232 static struct dhcps_client_lease *
235 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
236 struct dhcps_client_lease *lease;
237 lease = lookup_lease_mac(m->chaddr, m->hlen);
241 lease->flags &= ~LEASE_FLAGS_ALLOCATED;
247 add_msg_type(uint8_t *optptr, uint8_t type)
249 *optptr++ = DHCP_OPTION_MSG_TYPE;
256 add_server_id(uint8_t *optptr)
258 *optptr++ = DHCP_OPTION_SERVER_ID;
260 memcpy(optptr, &uip_hostaddr, 4);
265 add_lease_time(uint8_t *optptr)
268 *optptr++ = DHCP_OPTION_LEASE_TIME;
270 lt = UIP_HTONL(config->default_lease_time);
271 memcpy(optptr, <, 4);
277 add_end(uint8_t *optptr)
279 *optptr++ = DHCP_OPTION_END;
284 add_config(uint8_t *optptr)
286 if (config->flags & DHCP_CONF_NETMASK) {
287 *optptr++ = DHCP_OPTION_SUBNET_MASK;
289 memcpy(optptr, &config->netmask, 4);
292 if (config->flags & DHCP_CONF_DNSADDR) {
293 *optptr++ = DHCP_OPTION_DNS_SERVER;
295 memcpy(optptr, &config->dnsaddr, 4);
298 if (config->flags & DHCP_CONF_DEFAULT_ROUTER) {
299 *optptr++ = DHCP_OPTION_ROUTER;
301 memcpy(optptr, &config->default_router, 4);
316 memcpy(m->siaddr, &uip_hostaddr, 4);
319 memcpy(m->options, magic_cookie,
sizeof(magic_cookie));
327 send_offer(
struct uip_udp_conn *conn,
struct dhcps_client_lease *lease)
330 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
333 memcpy(&m->yiaddr, &lease->ipaddr,4);
335 end = add_msg_type(&m->options[4], DHCPOFFER);
336 end = add_server_id(end);
337 end = add_lease_time(end);
338 end = add_config(end);
345 send_ack(
struct uip_udp_conn *conn,
struct dhcps_client_lease *lease)
349 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
352 memcpy(&m->yiaddr, &lease->ipaddr,4);
354 end = add_msg_type(&m->options[4], DHCPACK);
355 end = add_server_id(end);
356 end = add_lease_time(end);
357 end = add_config(end);
359 memcpy(&ciaddr, &lease->ipaddr,4);
368 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
371 memset(&m->yiaddr, 0, 4);
373 end = add_msg_type(&m->options[4], DHCPNAK);
374 end = add_server_id(end);
383 PROCESS(dhcp_server_process,
"DHCP server");
390 static struct dhcps_client_lease *lease;
392 PRINTD(
"DHCP server starting\n");
396 if (!conn)
goto exit;
398 if (!send_conn)
goto exit;
406 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
409 if (m->op == DHCP_REQUEST && check_cookie() && m->hlen <= MAX_HLEN) {
410 uint8_t *opt = find_option(DHCP_OPTION_MSG_TYPE);
412 uint8_t mtype = opt[2];
413 if (opt[2] == DHCPDISCOVER) {
415 lease = choose_address();
417 lease->lease_end =
clock_seconds()+config->default_lease_time;
420 send_offer(conn,lease);
423 uint8_t *opt = find_option(DHCP_OPTION_SERVER_ID);
424 if (!opt || uip_ipaddr_cmp((
uip_ipaddr_t*)&opt[2], &uip_hostaddr)) {
425 if (mtype == DHCPREQUEST) {
427 lease = allocate_address();
431 send_nack(send_conn);
433 send_ack(send_conn,lease);
435 }
else if (mtype == DHCPRELEASE) {
438 }
else if (mtype == DHCPDECLINE) {
440 }
else if (mtype == DHCPINFORM) {
453 PRINTD(
"DHCP server exiting\n");
455 #ifdef ECLIPSE_STUB_CODE_ANALYSE 461 dhcps_init(
const struct dhcps_config *conf)
#define PROCESS(name, strname)
void process_start(struct process *p, const char *arg)
#define PRINTD(FORMAT, args...)
#define PROCESS_WAIT_EVENT_UNTIL(c)
void process_exit(struct process *p)
Cause a process to exit.
#define PROCESS_WAIT_EVENT()
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
void uip_send(const void *data, int len)
process_event_t tcpip_event
#define uip_ipaddr_copy(dest, src)
CCIF struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
uint8_t data[USBNET_RX_BUF_SIZE]
#define PROCESS_THREAD(name, ev, data)
#define uip_udp_bind(conn, port)
CCIF unsigned long clock_seconds(void)
CCIF void tcpip_poll_udp(struct uip_udp_conn *conn)