Free (GPLv2) TCP/IP stack developed by TASS Belgium

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Sat Aug 03 08:50:27 2013 +0000
Revision:
51:18637a3d071f
Parent:
29:1a47b7151851
Branch for CDC-ECM: Work in progress

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 29:1a47b7151851 1 /*********************************************************************
daniele 29:1a47b7151851 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 29:1a47b7151851 3 See LICENSE and COPYING for usage.
daniele 29:1a47b7151851 4
daniele 29:1a47b7151851 5
daniele 29:1a47b7151851 6 Authors: Frederik Van Slycken, Kristof Roelants
daniele 29:1a47b7151851 7 *********************************************************************/
daniele 29:1a47b7151851 8
daniele 29:1a47b7151851 9 #ifdef PICO_SUPPORT_DHCPD
daniele 29:1a47b7151851 10
daniele 29:1a47b7151851 11 #include "pico_dhcp_server.h"
daniele 29:1a47b7151851 12 #include "pico_stack.h"
daniele 29:1a47b7151851 13 #include "pico_config.h"
daniele 29:1a47b7151851 14 #include "pico_addressing.h"
daniele 29:1a47b7151851 15 #include "pico_socket.h"
daniele 29:1a47b7151851 16 #include "pico_arp.h"
daniele 29:1a47b7151851 17 #include <stdlib.h>
daniele 29:1a47b7151851 18
daniele 29:1a47b7151851 19 # define dhcpd_dbg(...) do{}while(0)
daniele 29:1a47b7151851 20 //# define dhcpd_dbg dbg
daniele 29:1a47b7151851 21
daniele 29:1a47b7151851 22 #define dhcpd_make_offer(x) dhcpd_make_reply(x, PICO_DHCP_MSG_OFFER)
daniele 29:1a47b7151851 23 #define dhcpd_make_ack(x) dhcpd_make_reply(x, PICO_DHCP_MSG_ACK)
daniele 29:1a47b7151851 24 #define ip_inrange(x) ((long_be(x) >= long_be(dn->settings->pool_start)) && (long_be(x) <= long_be(dn->settings->pool_end)))
daniele 29:1a47b7151851 25
daniele 29:1a47b7151851 26 static int dhcp_settings_cmp(void *ka, void *kb)
daniele 29:1a47b7151851 27 {
daniele 29:1a47b7151851 28 struct pico_dhcpd_settings *a = ka, *b = kb;
daniele 29:1a47b7151851 29 if (a->dev < b->dev)
daniele 29:1a47b7151851 30 return -1;
daniele 29:1a47b7151851 31 else if (a->dev > b->dev)
daniele 29:1a47b7151851 32 return 1;
daniele 29:1a47b7151851 33 else
daniele 29:1a47b7151851 34 return 0;
daniele 29:1a47b7151851 35 }
daniele 29:1a47b7151851 36 PICO_TREE_DECLARE(DHCPSettings, dhcp_settings_cmp);
daniele 29:1a47b7151851 37
daniele 29:1a47b7151851 38 static int dhcp_negotiations_cmp(void *ka, void *kb)
daniele 29:1a47b7151851 39 {
daniele 29:1a47b7151851 40 struct pico_dhcp_negotiation *a = ka, *b = kb;
daniele 29:1a47b7151851 41 if (a->xid < b->xid)
daniele 29:1a47b7151851 42 return -1;
daniele 29:1a47b7151851 43 else if (a->xid > b->xid)
daniele 29:1a47b7151851 44 return 1;
daniele 29:1a47b7151851 45 else
daniele 29:1a47b7151851 46 return 0;
daniele 29:1a47b7151851 47 }
daniele 29:1a47b7151851 48 PICO_TREE_DECLARE(DHCPNegotiations, dhcp_negotiations_cmp);
daniele 29:1a47b7151851 49
daniele 29:1a47b7151851 50 static struct pico_dhcp_negotiation *get_negotiation_by_xid(uint32_t xid)
daniele 29:1a47b7151851 51 {
daniele 29:1a47b7151851 52 struct pico_dhcp_negotiation test = { }, *neg = NULL;
daniele 29:1a47b7151851 53
daniele 29:1a47b7151851 54 test.xid = xid;
daniele 29:1a47b7151851 55 neg = pico_tree_findKey(&DHCPNegotiations, &test);
daniele 29:1a47b7151851 56 if (!neg)
daniele 29:1a47b7151851 57 return NULL;
daniele 29:1a47b7151851 58 else
daniele 29:1a47b7151851 59 return neg;
daniele 29:1a47b7151851 60 }
daniele 29:1a47b7151851 61
daniele 29:1a47b7151851 62 static void dhcpd_make_reply(struct pico_dhcp_negotiation *dn, uint8_t reply_type)
daniele 29:1a47b7151851 63 {
daniele 29:1a47b7151851 64 uint8_t buf_out[DHCPD_DATAGRAM_SIZE] = {0};
daniele 29:1a47b7151851 65 struct pico_dhcphdr *dh_out = (struct pico_dhcphdr *) buf_out;
daniele 29:1a47b7151851 66 struct pico_ip4 destination = { };
daniele 29:1a47b7151851 67 uint32_t bcast = dn->settings->my_ip.addr | ~(dn->settings->netmask.addr);
daniele 29:1a47b7151851 68 uint32_t dns_server = OPENDNS;
daniele 29:1a47b7151851 69 uint16_t port = PICO_DHCP_CLIENT_PORT;
daniele 29:1a47b7151851 70 int sent = 0;
daniele 29:1a47b7151851 71
daniele 29:1a47b7151851 72 memcpy(dh_out->hwaddr, dn->eth.addr, PICO_HLEN_ETHER);
daniele 29:1a47b7151851 73 dh_out->op = PICO_DHCP_OP_REPLY;
daniele 29:1a47b7151851 74 dh_out->htype = PICO_HTYPE_ETHER;
daniele 29:1a47b7151851 75 dh_out->hlen = PICO_HLEN_ETHER;
daniele 29:1a47b7151851 76 dh_out->xid = dn->xid;
daniele 29:1a47b7151851 77 dh_out->yiaddr = dn->ipv4.addr;
daniele 29:1a47b7151851 78 dh_out->siaddr = dn->settings->my_ip.addr;
daniele 29:1a47b7151851 79 dh_out->dhcp_magic = PICO_DHCPD_MAGIC_COOKIE;
daniele 29:1a47b7151851 80
daniele 29:1a47b7151851 81 /* Option: msg type, len 1 */
daniele 29:1a47b7151851 82 dh_out->options[0] = PICO_DHCPOPT_MSGTYPE;
daniele 29:1a47b7151851 83 dh_out->options[1] = 1;
daniele 29:1a47b7151851 84 dh_out->options[2] = reply_type;
daniele 29:1a47b7151851 85
daniele 29:1a47b7151851 86 /* Option: server id, len 4 */
daniele 29:1a47b7151851 87 dh_out->options[3] = PICO_DHCPOPT_SERVERID;
daniele 29:1a47b7151851 88 dh_out->options[4] = 4;
daniele 29:1a47b7151851 89 memcpy(dh_out->options + 5, &dn->settings->my_ip.addr, 4);
daniele 29:1a47b7151851 90
daniele 29:1a47b7151851 91 /* Option: Lease time, len 4 */
daniele 29:1a47b7151851 92 dh_out->options[9] = PICO_DHCPOPT_LEASETIME;
daniele 29:1a47b7151851 93 dh_out->options[10] = 4;
daniele 29:1a47b7151851 94 memcpy(dh_out->options + 11, &dn->settings->lease_time, 4);
daniele 29:1a47b7151851 95
daniele 29:1a47b7151851 96 /* Option: Netmask, len 4 */
daniele 29:1a47b7151851 97 dh_out->options[15] = PICO_DHCPOPT_NETMASK;
daniele 29:1a47b7151851 98 dh_out->options[16] = 4;
daniele 29:1a47b7151851 99 memcpy(dh_out->options + 17, &dn->settings->netmask.addr, 4);
daniele 29:1a47b7151851 100
daniele 29:1a47b7151851 101 /* Option: Router, len 4 */
daniele 29:1a47b7151851 102 dh_out->options[21] = PICO_DHCPOPT_ROUTER;
daniele 29:1a47b7151851 103 dh_out->options[22] = 4;
daniele 29:1a47b7151851 104 memcpy(dh_out->options + 23, &dn->settings->my_ip.addr, 4);
daniele 29:1a47b7151851 105
daniele 29:1a47b7151851 106 /* Option: Broadcast, len 4 */
daniele 29:1a47b7151851 107 dh_out->options[27] = PICO_DHCPOPT_BCAST;
daniele 29:1a47b7151851 108 dh_out->options[28] = 4;
daniele 29:1a47b7151851 109 memcpy(dh_out->options + 29, &bcast, 4);
daniele 29:1a47b7151851 110
daniele 29:1a47b7151851 111 /* Option: DNS, len 4 */
daniele 29:1a47b7151851 112 dh_out->options[33] = PICO_DHCPOPT_DNS;
daniele 29:1a47b7151851 113 dh_out->options[34] = 4;
daniele 29:1a47b7151851 114 memcpy(dh_out->options + 35, &dns_server, 4);
daniele 29:1a47b7151851 115
daniele 29:1a47b7151851 116 dh_out->options[40] = PICO_DHCPOPT_END;
daniele 29:1a47b7151851 117
daniele 29:1a47b7151851 118 destination.addr = dh_out->yiaddr;
daniele 29:1a47b7151851 119
daniele 29:1a47b7151851 120 sent = pico_socket_sendto(dn->settings->s, buf_out, DHCPD_DATAGRAM_SIZE, &destination, port);
daniele 29:1a47b7151851 121 if (sent < 0) {
daniele 29:1a47b7151851 122 dhcpd_dbg("DHCPD: sendto failed with code %d!\n", pico_err);
daniele 29:1a47b7151851 123 }
daniele 29:1a47b7151851 124 }
daniele 29:1a47b7151851 125
daniele 29:1a47b7151851 126 static void dhcp_recv(struct pico_socket *s, uint8_t *buffer, int len)
daniele 29:1a47b7151851 127 {
daniele 29:1a47b7151851 128 struct pico_dhcphdr *dhdr = (struct pico_dhcphdr *) buffer;
daniele 29:1a47b7151851 129 struct pico_dhcp_negotiation *dn = get_negotiation_by_xid(dhdr->xid);
daniele 29:1a47b7151851 130 struct pico_ip4* ipv4 = NULL;
daniele 29:1a47b7151851 131 struct pico_dhcpd_settings test, *settings = NULL;
daniele 29:1a47b7151851 132 uint8_t *nextopt, opt_data[20], opt_type;
daniele 29:1a47b7151851 133 int opt_len = 20;
daniele 29:1a47b7151851 134 uint8_t msg_type;
daniele 29:1a47b7151851 135 uint32_t msg_reqIP = 0;
daniele 29:1a47b7151851 136 uint32_t msg_servID = 0;
daniele 29:1a47b7151851 137
daniele 29:1a47b7151851 138 if (!is_options_valid(dhdr->options, len - sizeof(struct pico_dhcphdr))) {
daniele 29:1a47b7151851 139 dhcpd_dbg("DHCPD WARNING: invalid options in dhcp message\n");
daniele 29:1a47b7151851 140 return;
daniele 29:1a47b7151851 141 }
daniele 29:1a47b7151851 142
daniele 29:1a47b7151851 143 if (!dn) {
daniele 29:1a47b7151851 144 dn = pico_zalloc(sizeof(struct pico_dhcp_negotiation));
daniele 29:1a47b7151851 145 if (!dn) {
daniele 29:1a47b7151851 146 pico_err = PICO_ERR_ENOMEM;
daniele 29:1a47b7151851 147 return;
daniele 29:1a47b7151851 148 }
daniele 29:1a47b7151851 149 dn->xid = dhdr->xid;
daniele 29:1a47b7151851 150 dn->state = DHCPSTATE_DISCOVER;
daniele 29:1a47b7151851 151 memcpy(dn->eth.addr, dhdr->hwaddr, PICO_HLEN_ETHER);
daniele 29:1a47b7151851 152
daniele 29:1a47b7151851 153 test.dev = pico_ipv4_link_find(&s->local_addr.ip4);
daniele 29:1a47b7151851 154 settings = pico_tree_findKey(&DHCPSettings, &test);
daniele 29:1a47b7151851 155 if (settings) {
daniele 29:1a47b7151851 156 dn->settings = settings;
daniele 29:1a47b7151851 157 } else {
daniele 29:1a47b7151851 158 dhcpd_dbg("DHCPD WARNING: received DHCP message on unconfigured link %s\n", test.dev->name);
daniele 29:1a47b7151851 159 pico_free(dn);
daniele 29:1a47b7151851 160 return;
daniele 29:1a47b7151851 161 }
daniele 29:1a47b7151851 162
daniele 29:1a47b7151851 163 ipv4 = pico_arp_reverse_lookup(&dn->eth);
daniele 29:1a47b7151851 164 if (!ipv4) {
daniele 29:1a47b7151851 165 dn->ipv4.addr = settings->pool_next;
daniele 29:1a47b7151851 166 pico_arp_create_entry(dn->eth.addr, dn->ipv4, settings->dev);
daniele 29:1a47b7151851 167 settings->pool_next = long_be(long_be(settings->pool_next) + 1);
daniele 29:1a47b7151851 168 } else {
daniele 29:1a47b7151851 169 dn->ipv4.addr = ipv4->addr;
daniele 29:1a47b7151851 170 }
daniele 29:1a47b7151851 171
daniele 29:1a47b7151851 172 if (pico_tree_insert(&DHCPNegotiations, dn)) {
daniele 29:1a47b7151851 173 dhcpd_dbg("DHCPD WARNING: tried creating new negotation for existing xid %u\n", dn->xid);
daniele 29:1a47b7151851 174 pico_free(dn);
daniele 29:1a47b7151851 175 return; /* Element key already exists */
daniele 29:1a47b7151851 176 }
daniele 29:1a47b7151851 177 }
daniele 29:1a47b7151851 178
daniele 29:1a47b7151851 179 if (!ip_inrange(dn->ipv4.addr))
daniele 29:1a47b7151851 180 return;
daniele 29:1a47b7151851 181
daniele 29:1a47b7151851 182 opt_type = dhcp_get_next_option(dhdr->options, opt_data, &opt_len, &nextopt);
daniele 29:1a47b7151851 183 while (opt_type != PICO_DHCPOPT_END) {
daniele 29:1a47b7151851 184 /* parse interesting options here */
daniele 29:1a47b7151851 185 //dhcpd_dbg("DHCPD sever: opt_type %x, opt_data[0]%d\n", opt_type, opt_data[0]);
daniele 29:1a47b7151851 186 switch(opt_type){
daniele 29:1a47b7151851 187 case PICO_DHCPOPT_MSGTYPE:
daniele 29:1a47b7151851 188 msg_type = opt_data[0];
daniele 29:1a47b7151851 189 break;
daniele 29:1a47b7151851 190 case PICO_DHCPOPT_REQIP:
daniele 29:1a47b7151851 191 //dhcpd_dbg("DHCPD sever: opt_type %x, opt_len%d\n", opt_type, opt_len);
daniele 29:1a47b7151851 192 if( opt_len == 4)
daniele 29:1a47b7151851 193 {
daniele 29:1a47b7151851 194 msg_reqIP = ( opt_data[0] << 24 );
daniele 29:1a47b7151851 195 msg_reqIP |= ( opt_data[1] << 16 );
daniele 29:1a47b7151851 196 msg_reqIP |= ( opt_data[2] << 8 );
daniele 29:1a47b7151851 197 msg_reqIP |= ( opt_data[3] );
daniele 29:1a47b7151851 198 //dhcpd_dbg("DHCPD sever: msg_reqIP %x, opt_data[0] %x,[1] %x,[2] %x,[3] %x\n", msg_reqIP, opt_data[0],opt_data[1],opt_data[2],opt_data[3]);
daniele 29:1a47b7151851 199 };
daniele 29:1a47b7151851 200 break;
daniele 29:1a47b7151851 201 case PICO_DHCPOPT_SERVERID:
daniele 29:1a47b7151851 202 //dhcpd_dbg("DHCPD sever: opt_type %x, opt_len%d\n", opt_type, opt_len);
daniele 29:1a47b7151851 203 if( opt_len == 4)
daniele 29:1a47b7151851 204 {
daniele 29:1a47b7151851 205 msg_servID = ( opt_data[0] << 24 );
daniele 29:1a47b7151851 206 msg_servID |= ( opt_data[1] << 16 );
daniele 29:1a47b7151851 207 msg_servID |= ( opt_data[2] << 8 );
daniele 29:1a47b7151851 208 msg_servID |= ( opt_data[3] );
daniele 29:1a47b7151851 209 //dhcpd_dbg("DHCPD sever: msg_servID %x, opt_data[0] %x,[1] %x,[2] %x,[3] %x\n", msg_servID, opt_data[0],opt_data[1],opt_data[2],opt_data[3]);
daniele 29:1a47b7151851 210 };
daniele 29:1a47b7151851 211 break;
daniele 29:1a47b7151851 212 default:
daniele 29:1a47b7151851 213 break;
daniele 29:1a47b7151851 214 }
daniele 29:1a47b7151851 215
daniele 29:1a47b7151851 216 opt_len = 20;
daniele 29:1a47b7151851 217 opt_type = dhcp_get_next_option(NULL, opt_data, &opt_len, &nextopt);
daniele 29:1a47b7151851 218 }
daniele 29:1a47b7151851 219
daniele 29:1a47b7151851 220 //dhcpd_dbg("DHCPD sever: msg_type %d, dn->state %d\n", msg_type, dn->state);
daniele 29:1a47b7151851 221 //dhcpd_dbg("DHCPD sever: msg_reqIP %x, dn->msg_servID %x\n", msg_reqIP, msg_servID);
daniele 29:1a47b7151851 222 //dhcpd_dbg("DHCPD sever: dhdr->ciaddr %x, dhdr->yiaddr %x, dn->ipv4.addr %x\n", dhdr->ciaddr,dhdr->yiaddr,dn->ipv4.addr);
daniele 29:1a47b7151851 223
daniele 29:1a47b7151851 224 if (msg_type == PICO_DHCP_MSG_DISCOVER)
daniele 29:1a47b7151851 225 {
daniele 29:1a47b7151851 226 dhcpd_make_offer(dn);
daniele 29:1a47b7151851 227 dn->state = DHCPSTATE_OFFER;
daniele 29:1a47b7151851 228 return;
daniele 29:1a47b7151851 229 }
daniele 29:1a47b7151851 230 else if ((msg_type == PICO_DHCP_MSG_REQUEST)&&( dn->state == DHCPSTATE_OFFER))
daniele 29:1a47b7151851 231 {
daniele 29:1a47b7151851 232 dhcpd_make_ack(dn);
daniele 29:1a47b7151851 233 dn->state = DHCPSTATE_BOUND;
daniele 29:1a47b7151851 234 return;
daniele 29:1a47b7151851 235 }
daniele 29:1a47b7151851 236 else if ((msg_type == PICO_DHCP_MSG_REQUEST)&&( dn->state == DHCPSTATE_BOUND))
daniele 29:1a47b7151851 237 {
daniele 29:1a47b7151851 238 if( ( msg_servID == 0 )
daniele 29:1a47b7151851 239 &&( msg_reqIP == 0 )
daniele 29:1a47b7151851 240 &&( dhdr->ciaddr == dn->ipv4.addr)
daniele 29:1a47b7151851 241 )
daniele 29:1a47b7151851 242 {
daniele 29:1a47b7151851 243 dhcpd_make_ack(dn);
daniele 29:1a47b7151851 244 return;
daniele 29:1a47b7151851 245 }
daniele 29:1a47b7151851 246 }
daniele 29:1a47b7151851 247 }
daniele 29:1a47b7151851 248
daniele 29:1a47b7151851 249 static void pico_dhcpd_wakeup(uint16_t ev, struct pico_socket *s)
daniele 29:1a47b7151851 250 {
daniele 29:1a47b7151851 251 uint8_t buf[DHCPD_DATAGRAM_SIZE] = { };
daniele 29:1a47b7151851 252 int r = 0;
daniele 29:1a47b7151851 253 uint32_t peer = 0;
daniele 29:1a47b7151851 254 uint16_t port = 0;
daniele 29:1a47b7151851 255
daniele 29:1a47b7151851 256 dhcpd_dbg("DHCPD: called dhcpd_wakeup\n");
daniele 29:1a47b7151851 257 if (ev == PICO_SOCK_EV_RD) {
daniele 29:1a47b7151851 258 do {
daniele 29:1a47b7151851 259 r = pico_socket_recvfrom(s, buf, DHCPD_DATAGRAM_SIZE, &peer, &port);
daniele 29:1a47b7151851 260 if (r > 0 && port == PICO_DHCP_CLIENT_PORT) {
daniele 29:1a47b7151851 261 dhcp_recv(s, buf, r);
daniele 29:1a47b7151851 262 }
daniele 29:1a47b7151851 263 } while(r>0);
daniele 29:1a47b7151851 264 }
daniele 29:1a47b7151851 265 }
daniele 29:1a47b7151851 266
daniele 29:1a47b7151851 267 int pico_dhcp_server_initiate(struct pico_dhcpd_settings *setting)
daniele 29:1a47b7151851 268 {
daniele 29:1a47b7151851 269 struct pico_dhcpd_settings *settings = NULL;
daniele 29:1a47b7151851 270 struct pico_ipv4_link *link = NULL;
daniele 29:1a47b7151851 271 uint16_t port = PICO_DHCPD_PORT;
daniele 29:1a47b7151851 272
daniele 29:1a47b7151851 273 if (!setting) {
daniele 29:1a47b7151851 274 pico_err = PICO_ERR_EINVAL;
daniele 29:1a47b7151851 275 return -1;
daniele 29:1a47b7151851 276 }
daniele 29:1a47b7151851 277
daniele 29:1a47b7151851 278 if (!setting->my_ip.addr) {
daniele 29:1a47b7151851 279 pico_err = PICO_ERR_EINVAL;
daniele 29:1a47b7151851 280 dhcpd_dbg("DHCPD: IP address of interface was not supplied\n");
daniele 29:1a47b7151851 281 return -1;
daniele 29:1a47b7151851 282 }
daniele 29:1a47b7151851 283
daniele 29:1a47b7151851 284 link = pico_ipv4_link_get(&setting->my_ip);
daniele 29:1a47b7151851 285 if (!link) {
daniele 29:1a47b7151851 286 pico_err = PICO_ERR_EINVAL;
daniele 29:1a47b7151851 287 dhcpd_dbg("DHCPD: no link with IP %X found\n", setting->my_ip.addr);
daniele 29:1a47b7151851 288 return -1;
daniele 29:1a47b7151851 289 }
daniele 29:1a47b7151851 290
daniele 29:1a47b7151851 291 settings = pico_zalloc(sizeof(struct pico_dhcpd_settings));
daniele 29:1a47b7151851 292 if (!settings) {
daniele 29:1a47b7151851 293 pico_err = PICO_ERR_ENOMEM;
daniele 29:1a47b7151851 294 return -1;
daniele 29:1a47b7151851 295 }
daniele 29:1a47b7151851 296 memcpy(settings, setting, sizeof(struct pico_dhcpd_settings));
daniele 29:1a47b7151851 297
daniele 29:1a47b7151851 298 settings->dev = link->dev;
daniele 29:1a47b7151851 299 dhcpd_dbg("DHCPD: configuring DHCP server for link %s\n", link->dev->name);
daniele 29:1a47b7151851 300 settings->my_ip.addr = link->address.addr;
daniele 29:1a47b7151851 301 dhcpd_dbg("DHCPD: using server addr %X\n", long_be(settings->my_ip.addr));
daniele 29:1a47b7151851 302 settings->netmask.addr = link->netmask.addr;
daniele 29:1a47b7151851 303 dhcpd_dbg("DHCPD: using netmask %X\n", long_be(settings->netmask.addr));
daniele 29:1a47b7151851 304
daniele 29:1a47b7151851 305 /* default values if not provided */
daniele 29:1a47b7151851 306 if (settings->pool_start == 0)
daniele 29:1a47b7151851 307 settings->pool_start = (settings->my_ip.addr & settings->netmask.addr) | POOL_START;
daniele 29:1a47b7151851 308 dhcpd_dbg("DHCPD: using pool_start %X\n", long_be(settings->pool_start));
daniele 29:1a47b7151851 309 if (settings->pool_end == 0)
daniele 29:1a47b7151851 310 settings->pool_end = (settings->my_ip.addr & settings->netmask.addr) | POOL_END;
daniele 29:1a47b7151851 311 dhcpd_dbg("DHCPD: using pool_end %x\n", long_be(settings->pool_end));
daniele 29:1a47b7151851 312 if (settings->lease_time == 0)
daniele 29:1a47b7151851 313 settings->lease_time = LEASE_TIME;
daniele 29:1a47b7151851 314 dhcpd_dbg("DHCPD: using lease time %x\n", long_be(settings->lease_time));
daniele 29:1a47b7151851 315 settings->pool_next = settings->pool_start;
daniele 29:1a47b7151851 316
daniele 29:1a47b7151851 317 settings->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcpd_wakeup);
daniele 29:1a47b7151851 318 if (!settings->s) {
daniele 29:1a47b7151851 319 dhcpd_dbg("DHCP: could not open client socket\n");
daniele 29:1a47b7151851 320 pico_free(settings);
daniele 29:1a47b7151851 321 return -1;
daniele 29:1a47b7151851 322 }
daniele 29:1a47b7151851 323 if (pico_socket_bind(settings->s, &settings->my_ip, &port) != 0) {
daniele 29:1a47b7151851 324 dhcpd_dbg("DHCP: could not bind server socket (%s)\n", strerror(pico_err));
daniele 29:1a47b7151851 325 pico_free(settings);
daniele 29:1a47b7151851 326 return -1;
daniele 29:1a47b7151851 327 }
daniele 29:1a47b7151851 328
daniele 29:1a47b7151851 329 if (pico_tree_insert(&DHCPSettings, settings)) {
daniele 29:1a47b7151851 330 dhcpd_dbg("DHCPD ERROR: link %s already configured\n", link->dev->name);
daniele 29:1a47b7151851 331 pico_err = PICO_ERR_EINVAL;
daniele 29:1a47b7151851 332 pico_free(settings);
daniele 29:1a47b7151851 333 return -1; /* Element key already exists */
daniele 29:1a47b7151851 334 }
daniele 29:1a47b7151851 335 dhcpd_dbg("DHCPD: configured DHCP server for link %s\n", link->dev->name);
daniele 29:1a47b7151851 336
daniele 29:1a47b7151851 337 return 0;
daniele 29:1a47b7151851 338 }
daniele 29:1a47b7151851 339 #endif /* PICO_SUPPORT_DHCP */