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

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
daniele
Date:
Sun Jun 16 20:19:44 2013 +0000
Revision:
29:1a47b7151851
Child:
51:ab4529a384a6
Updated from masterbranch;

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 */