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