38 #include "contiki-net.h"
42 uint8_t op, htype, hlen, hops;
50 #ifndef UIP_CONF_DHCP_LIGHT
57 #define BOOTP_BROADCAST 0x8000
59 #define DHCP_REQUEST 1
61 #define DHCP_HTYPE_ETHERNET 1
62 #define DHCP_HLEN_ETHERNET 6
63 #define DHCP_MSG_LEN 236
65 #define DHCPS_SERVER_PORT 67
66 #define DHCPS_CLIENT_PORT 68
68 #define DHCPDISCOVER 1
77 #define DHCP_OPTION_SUBNET_MASK 1
78 #define DHCP_OPTION_ROUTER 3
79 #define DHCP_OPTION_DNS_SERVER 6
80 #define DHCP_OPTION_REQ_IPADDR 50
81 #define DHCP_OPTION_LEASE_TIME 51
82 #define DHCP_OPTION_MSG_TYPE 53
83 #define DHCP_OPTION_SERVER_ID 54
84 #define DHCP_OPTION_REQ_LIST 55
85 #define DHCP_OPTION_END 255
89 #define LEASE_FLAGS_ALLOCATED 0x01
90 #define LEASE_FLAGS_VALID 0x02
94 static const struct dhcps_config *config;
98 find_option(uint8_t option)
100 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
101 uint8_t *optptr = &m->options[4];
103 while(optptr < end && *optptr != DHCP_OPTION_END) {
104 if(*optptr == option) {
107 optptr += optptr[1] + 2;
112 static const uint8_t magic_cookie[4] = {99, 130, 83, 99};
117 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
118 return memcmp(m->options, magic_cookie, 4) == 0;
122 static struct dhcps_client_lease *
123 lookup_lease_mac(
const uint8_t *chaddr, uint8_t hlen)
125 struct dhcps_client_lease *lease = config->leases;
126 struct dhcps_client_lease *end = config->leases + config->num_leases;
127 while(lease != end) {
128 if (lease->flags & LEASE_FLAGS_VALID
129 && memcmp(lease->chaddr, chaddr, hlen) == 0) {
137 static struct dhcps_client_lease *
138 lookup_lease_ip(
const uip_ipaddr_t *ip)
140 struct dhcps_client_lease *lease = config->leases;
141 struct dhcps_client_lease *end = config->leases + config->num_leases;
142 while(lease != end) {
143 if (uip_ipaddr_cmp(&lease->ipaddr, ip)) {
151 static struct dhcps_client_lease *
152 find_free_lease(
void)
154 struct dhcps_client_lease *found =
NULL;
155 struct dhcps_client_lease *lease = config->leases;
156 struct dhcps_client_lease *end = config->leases + config->num_leases;
157 while(lease != end) {
158 if (!(lease->flags & LEASE_FLAGS_VALID))
return lease;
159 if (!(lease->flags & LEASE_FLAGS_ALLOCATED)) found = lease;
165 struct dhcps_client_lease *
166 init_lease(
struct dhcps_client_lease *lease,
167 const uint8_t *chaddr, uint8_t hlen)
170 memcpy(lease->chaddr, chaddr, hlen);
171 lease->flags = LEASE_FLAGS_VALID;
177 static struct dhcps_client_lease *
180 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
181 struct dhcps_client_lease *lease;
182 lease = lookup_lease_mac(m->chaddr, m->hlen);
188 opt = find_option(DHCP_OPTION_REQ_IPADDR);
189 if (opt && (lease = lookup_lease_ip((uip_ipaddr_t*)&opt[2]))
190 && !(lease->flags & LEASE_FLAGS_ALLOCATED)) {
191 return init_lease(lease, m->chaddr,m->hlen);
194 lease = find_free_lease();
196 return init_lease(lease, m->chaddr,m->hlen);
201 static struct dhcps_client_lease *
204 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
205 struct dhcps_client_lease *lease;
206 lease = lookup_lease_mac(m->chaddr, m->hlen);
209 opt = find_option(DHCP_OPTION_REQ_IPADDR);
210 if (!(opt && (lease = lookup_lease_ip((uip_ipaddr_t*)&opt[2]))
211 && !(lease->flags & LEASE_FLAGS_ALLOCATED))) {
215 lease->lease_end =
clock_seconds()+config->default_lease_time;
216 lease->flags |= LEASE_FLAGS_ALLOCATED;
220 static struct dhcps_client_lease *
223 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
224 struct dhcps_client_lease *lease;
225 lease = lookup_lease_mac(m->chaddr, m->hlen);
229 lease->flags &= ~LEASE_FLAGS_ALLOCATED;
235 add_msg_type(uint8_t *optptr, uint8_t type)
237 *optptr++ = DHCP_OPTION_MSG_TYPE;
244 add_server_id(uint8_t *optptr)
246 *optptr++ = DHCP_OPTION_SERVER_ID;
248 memcpy(optptr, &uip_hostaddr, 4);
253 add_lease_time(uint8_t *optptr)
256 *optptr++ = DHCP_OPTION_LEASE_TIME;
258 lt = UIP_HTONL(config->default_lease_time);
259 memcpy(optptr, <, 4);
265 add_end(uint8_t *optptr)
267 *optptr++ = DHCP_OPTION_END;
272 add_config(uint8_t *optptr)
274 if (config->flags & DHCP_CONF_NETMASK) {
275 *optptr++ = DHCP_OPTION_SUBNET_MASK;
277 memcpy(optptr, &config->netmask, 4);
280 if (config->flags & DHCP_CONF_DNSADDR) {
281 *optptr++ = DHCP_OPTION_DNS_SERVER;
283 memcpy(optptr, &config->dnsaddr, 4);
286 if (config->flags & DHCP_CONF_DEFAULT_ROUTER) {
287 *optptr++ = DHCP_OPTION_ROUTER;
289 memcpy(optptr, &config->default_router, 4);
304 memcpy(m->siaddr, &uip_hostaddr, 4);
307 memcpy(m->options, magic_cookie,
sizeof(magic_cookie));
310 static uip_ipaddr_t any_addr;
311 static uip_ipaddr_t bcast_addr;
315 send_offer(
struct uip_udp_conn *conn,
struct dhcps_client_lease *lease)
318 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
321 memcpy(&m->yiaddr, &lease->ipaddr,4);
323 end = add_msg_type(&m->options[4], DHCPOFFER);
324 end = add_server_id(end);
325 end = add_lease_time(end);
326 end = add_config(end);
333 send_ack(
struct uip_udp_conn *conn,
struct dhcps_client_lease *lease)
337 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
340 memcpy(&m->yiaddr, &lease->ipaddr,4);
342 end = add_msg_type(&m->options[4], DHCPACK);
343 end = add_server_id(end);
344 end = add_lease_time(end);
345 end = add_config(end);
347 memcpy(&ciaddr, &lease->ipaddr,4);
356 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
359 memset(&m->yiaddr, 0, 4);
361 end = add_msg_type(&m->options[4], DHCPNAK);
362 end = add_server_id(end);
371 PROCESS(dhcp_server_process,
"DHCP server");
378 static struct dhcps_client_lease *lease;
380 printf(
"DHCP server starting\n");
384 if (!conn)
goto exit;
386 if (!send_conn)
goto exit;
394 struct dhcp_msg *m = (
struct dhcp_msg *)
uip_appdata;
395 struct uip_udpip_hdr *header = (
struct uip_udpip_hdr *)&uip_buf[
UIP_LLH_LEN];
397 if (m->op == DHCP_REQUEST && check_cookie() && m->hlen <= MAX_HLEN) {
398 uint8_t *opt = find_option(DHCP_OPTION_MSG_TYPE);
400 uint8_t mtype = opt[2];
401 if (opt[2] == DHCPDISCOVER) {
402 printf(
"Discover\n");
403 lease = choose_address();
405 lease->lease_end =
clock_seconds()+config->default_lease_time;
408 send_offer(conn,lease);
411 uint8_t *opt = find_option(DHCP_OPTION_SERVER_ID);
412 if (!opt || uip_ipaddr_cmp((uip_ipaddr_t*)&opt[2], &uip_hostaddr)) {
413 if (mtype == DHCPREQUEST) {
415 lease = allocate_address();
419 send_nack(send_conn);
421 send_ack(send_conn,lease);
423 }
else if (mtype == DHCPRELEASE) {
426 }
else if (mtype == DHCPDECLINE) {
428 }
else if (mtype == DHCPINFORM) {
441 printf(
"DHCP server exiting\n");
446 dhcps_init(
const struct dhcps_config *conf)
#define PROCESS_BEGIN()
Define the beginning of a process.
CCIF struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
CCIF void uip_send(const void *data, int len)
Send data on the current connection.
#define uip_newdata()
Is new incoming data available?
#define uip_udp_bind(conn, port)
Bind a UDP connection to a local port.
#define NULL
The null pointer.
#define uip_poll()
Is the connection being polled by uIP?
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
CCIF void tcpip_poll_udp(struct uip_udp_conn *conn)
Cause a specified UDP connection to be polled.
uip_ipaddr_t ripaddr
The IP address of the remote peer.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_END()
Define the end of a process.
#define UIP_LLH_LEN
The link level header length.
Macros and definitions for the ARP module.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
#define PROCESS(name, strname)
Declare a process.
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
#define CC_REGISTER_ARG
Configure if the C compiler supports the "register" keyword for function arguments.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
process_event_t tcpip_event
The uIP event.
void process_start(struct process *p, process_data_t data)
Start a process.
Representation of a uIP UDP connection.
#define uip_ipaddr(addr, addr0, addr1, addr2, addr3)
Construct an IP address from four bytes.
uip_appdata
Pointer to the application data in the packet buffer.