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:
tass
Date:
Thu Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
154:6c0e92a80c4a
Adding TCP flag for FIN.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
tass 152:a3d286bf94e5 2 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
TASS Belgium NV 131:4758606c9316 5 Authors: Kristof Roelants, Frederik Van Slycken
TASS Belgium NV 131:4758606c9316 6 *********************************************************************/
tass 68:0847e35d08a6 7
tass 68:0847e35d08a6 8
tass 68:0847e35d08a6 9 #include "pico_dhcp_client.h"
tass 68:0847e35d08a6 10 #include "pico_stack.h"
tass 68:0847e35d08a6 11 #include "pico_config.h"
tass 68:0847e35d08a6 12 #include "pico_device.h"
tass 68:0847e35d08a6 13 #include "pico_ipv4.h"
tass 68:0847e35d08a6 14 #include "pico_socket.h"
tass 68:0847e35d08a6 15 #include "pico_eth.h"
tass 68:0847e35d08a6 16
tass 152:a3d286bf94e5 17 #if (defined PICO_SUPPORT_DHCPC && defined PICO_SUPPORT_UDP)
TASS Belgium NV 131:4758606c9316 18 #define dhcpc_dbg(...) do {} while(0)
TASS Belgium NV 131:4758606c9316 19 /* #define dhcpc_dbg dbg */
tass 68:0847e35d08a6 20
tass 68:0847e35d08a6 21 /* timer values */
tass 152:a3d286bf94e5 22 #define DHCP_CLIENT_REINIT 6000 /* msec */
tass 68:0847e35d08a6 23 #define DHCP_CLIENT_RETRANS 4 /* sec */
tass 68:0847e35d08a6 24 #define DHCP_CLIENT_RETRIES 3
tass 68:0847e35d08a6 25
tass 68:0847e35d08a6 26 #define DHCP_CLIENT_TIMER_STOPPED 0
tass 68:0847e35d08a6 27 #define DHCP_CLIENT_TIMER_STARTED 1
tass 68:0847e35d08a6 28
tass 68:0847e35d08a6 29 /* maximum size of a DHCP message */
tass 152:a3d286bf94e5 30 #define DHCP_CLIENT_MAXMSGZISE (PICO_IP_MRU - PICO_SIZE_IP4HDR)
tass 68:0847e35d08a6 31
tass 68:0847e35d08a6 32 enum dhcp_client_state {
TASS Belgium NV 131:4758606c9316 33 DHCP_CLIENT_STATE_INIT_REBOOT = 0,
TASS Belgium NV 131:4758606c9316 34 DHCP_CLIENT_STATE_REBOOTING,
TASS Belgium NV 131:4758606c9316 35 DHCP_CLIENT_STATE_INIT,
TASS Belgium NV 131:4758606c9316 36 DHCP_CLIENT_STATE_SELECTING,
TASS Belgium NV 131:4758606c9316 37 DHCP_CLIENT_STATE_REQUESTING,
TASS Belgium NV 131:4758606c9316 38 DHCP_CLIENT_STATE_BOUND,
TASS Belgium NV 131:4758606c9316 39 DHCP_CLIENT_STATE_RENEWING,
TASS Belgium NV 131:4758606c9316 40 DHCP_CLIENT_STATE_REBINDING
tass 68:0847e35d08a6 41 };
tass 68:0847e35d08a6 42
tass 152:a3d286bf94e5 43
tass 152:a3d286bf94e5 44 #define PICO_DHCPC_TIMER_INIT 0
tass 152:a3d286bf94e5 45 #define PICO_DHCPC_TIMER_REQUEST 1
tass 152:a3d286bf94e5 46 #define PICO_DHCPC_TIMER_RENEW 2
tass 152:a3d286bf94e5 47 #define PICO_DHCPC_TIMER_REBIND 3
tass 152:a3d286bf94e5 48 #define PICO_DHCPC_TIMER_T1 4
tass 152:a3d286bf94e5 49 #define PICO_DHCPC_TIMER_T2 5
tass 152:a3d286bf94e5 50 #define PICO_DHCPC_TIMER_LEASE 6
tass 152:a3d286bf94e5 51 #define PICO_DHCPC_TIMER_ARRAY_SIZE 7
tass 152:a3d286bf94e5 52
tass 68:0847e35d08a6 53 struct dhcp_client_timer
tass 68:0847e35d08a6 54 {
TASS Belgium NV 131:4758606c9316 55 uint8_t state;
tass 152:a3d286bf94e5 56 unsigned int type;
tass 152:a3d286bf94e5 57 uint32_t xid;
tass 68:0847e35d08a6 58 };
tass 68:0847e35d08a6 59
tass 68:0847e35d08a6 60 struct pico_dhcp_client_cookie
tass 68:0847e35d08a6 61 {
TASS Belgium NV 131:4758606c9316 62 uint8_t event;
TASS Belgium NV 131:4758606c9316 63 uint8_t retry;
TASS Belgium NV 131:4758606c9316 64 uint32_t xid;
TASS Belgium NV 131:4758606c9316 65 uint32_t *uid;
TASS Belgium NV 131:4758606c9316 66 enum dhcp_client_state state;
TASS Belgium NV 131:4758606c9316 67 void (*cb)(void*dhcpc, int code);
TASS Belgium NV 131:4758606c9316 68 pico_time init_timestamp;
TASS Belgium NV 131:4758606c9316 69 struct pico_socket *s;
TASS Belgium NV 131:4758606c9316 70 struct pico_ip4 address;
TASS Belgium NV 131:4758606c9316 71 struct pico_ip4 netmask;
TASS Belgium NV 131:4758606c9316 72 struct pico_ip4 gateway;
tass 152:a3d286bf94e5 73 struct pico_ip4 nameserver[2];
TASS Belgium NV 131:4758606c9316 74 struct pico_ip4 server_id;
TASS Belgium NV 131:4758606c9316 75 struct pico_device *dev;
tass 152:a3d286bf94e5 76 struct dhcp_client_timer *timer[PICO_DHCPC_TIMER_ARRAY_SIZE];
tass 152:a3d286bf94e5 77 uint32_t t1_time;
tass 152:a3d286bf94e5 78 uint32_t t2_time;
tass 152:a3d286bf94e5 79 uint32_t lease_time;
tass 152:a3d286bf94e5 80 uint32_t renew_time;
tass 152:a3d286bf94e5 81 uint32_t rebind_time;
tass 68:0847e35d08a6 82 };
tass 68:0847e35d08a6 83
tass 68:0847e35d08a6 84 static int pico_dhcp_client_init(struct pico_dhcp_client_cookie *dhcpc);
tass 68:0847e35d08a6 85 static int reset(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
tass 70:cd218dd180e5 86 static int8_t pico_dhcp_client_msg(struct pico_dhcp_client_cookie *dhcpc, uint8_t msg_type);
tass 68:0847e35d08a6 87 static void pico_dhcp_client_wakeup(uint16_t ev, struct pico_socket *s);
tass 68:0847e35d08a6 88 static void pico_dhcp_state_machine(uint8_t event, struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
tass 68:0847e35d08a6 89
tass 152:a3d286bf94e5 90 static const struct pico_ip4 bcast_netmask = {
tass 152:a3d286bf94e5 91 .addr = 0xFFFFFFFF
tass 152:a3d286bf94e5 92 };
tass 152:a3d286bf94e5 93
tass 152:a3d286bf94e5 94 static struct pico_ip4 inaddr_any = {
tass 152:a3d286bf94e5 95 0
tass 152:a3d286bf94e5 96 };
tass 152:a3d286bf94e5 97
tass 152:a3d286bf94e5 98
tass 68:0847e35d08a6 99 static int dhcp_cookies_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 100 {
TASS Belgium NV 131:4758606c9316 101 struct pico_dhcp_client_cookie *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 102 if (a->xid == b->xid)
TASS Belgium NV 131:4758606c9316 103 return 0;
TASS Belgium NV 131:4758606c9316 104
tass picotcp@tass.be 149:5f4cb161cec3 105 return (a->xid < b->xid) ? (-1) : (1);
TASS Belgium NV 131:4758606c9316 106 }
tass 68:0847e35d08a6 107 PICO_TREE_DECLARE(DHCPCookies, dhcp_cookies_cmp);
tass 68:0847e35d08a6 108
tass 68:0847e35d08a6 109 static struct pico_dhcp_client_cookie *pico_dhcp_client_add_cookie(uint32_t xid, struct pico_device *dev, void (*cb)(void *dhcpc, int code), uint32_t *uid)
tass 68:0847e35d08a6 110 {
TASS Belgium NV 131:4758606c9316 111 struct pico_dhcp_client_cookie *dhcpc = NULL, *found = NULL, test = {
TASS Belgium NV 131:4758606c9316 112 0
TASS Belgium NV 131:4758606c9316 113 };
TASS Belgium NV 131:4758606c9316 114
TASS Belgium NV 131:4758606c9316 115 test.xid = xid;
TASS Belgium NV 131:4758606c9316 116 found = pico_tree_findKey(&DHCPCookies, &test);
TASS Belgium NV 131:4758606c9316 117 if (found) {
TASS Belgium NV 131:4758606c9316 118 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 119 return NULL;
TASS Belgium NV 131:4758606c9316 120 }
tass 68:0847e35d08a6 121
tass picotcp@tass.be 149:5f4cb161cec3 122 dhcpc = PICO_ZALLOC(sizeof(struct pico_dhcp_client_cookie));
TASS Belgium NV 131:4758606c9316 123 if (!dhcpc) {
TASS Belgium NV 131:4758606c9316 124 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 125 return NULL;
TASS Belgium NV 131:4758606c9316 126 }
tass 68:0847e35d08a6 127
TASS Belgium NV 131:4758606c9316 128 dhcpc->state = DHCP_CLIENT_STATE_INIT;
TASS Belgium NV 131:4758606c9316 129 dhcpc->xid = xid;
TASS Belgium NV 131:4758606c9316 130 dhcpc->uid = uid;
TASS Belgium NV 131:4758606c9316 131 *(dhcpc->uid) = 0;
TASS Belgium NV 131:4758606c9316 132 dhcpc->cb = cb;
TASS Belgium NV 131:4758606c9316 133 dhcpc->dev = dev;
tass 68:0847e35d08a6 134
TASS Belgium NV 131:4758606c9316 135 pico_tree_insert(&DHCPCookies, dhcpc);
TASS Belgium NV 131:4758606c9316 136 return dhcpc;
tass 68:0847e35d08a6 137 }
tass 68:0847e35d08a6 138
tass 152:a3d286bf94e5 139 static void pico_dhcp_client_stop_timers(struct pico_dhcp_client_cookie *dhcpc);
tass 68:0847e35d08a6 140 static int pico_dhcp_client_del_cookie(uint32_t xid)
tass 68:0847e35d08a6 141 {
TASS Belgium NV 131:4758606c9316 142 struct pico_dhcp_client_cookie test = {
TASS Belgium NV 131:4758606c9316 143 0
TASS Belgium NV 131:4758606c9316 144 }, *found = NULL;
tass 68:0847e35d08a6 145
TASS Belgium NV 131:4758606c9316 146 test.xid = xid;
TASS Belgium NV 131:4758606c9316 147 found = pico_tree_findKey(&DHCPCookies, &test);
TASS Belgium NV 131:4758606c9316 148 if (!found)
TASS Belgium NV 131:4758606c9316 149 return -1;
tass 68:0847e35d08a6 150
tass 152:a3d286bf94e5 151 pico_dhcp_client_stop_timers(found);
TASS Belgium NV 131:4758606c9316 152 pico_socket_close(found->s);
tass 152:a3d286bf94e5 153 found->s = NULL;
TASS Belgium NV 131:4758606c9316 154 pico_ipv4_link_del(found->dev, found->address);
TASS Belgium NV 131:4758606c9316 155 pico_tree_delete(&DHCPCookies, found);
tass picotcp@tass.be 149:5f4cb161cec3 156 PICO_FREE(found);
TASS Belgium NV 131:4758606c9316 157 return 0;
tass 68:0847e35d08a6 158 }
tass 68:0847e35d08a6 159
tass 68:0847e35d08a6 160 static struct pico_dhcp_client_cookie *pico_dhcp_client_find_cookie(uint32_t xid)
tass 68:0847e35d08a6 161 {
TASS Belgium NV 131:4758606c9316 162 struct pico_dhcp_client_cookie test = {
TASS Belgium NV 131:4758606c9316 163 0
TASS Belgium NV 131:4758606c9316 164 }, *found = NULL;
tass 68:0847e35d08a6 165
TASS Belgium NV 131:4758606c9316 166 test.xid = xid;
TASS Belgium NV 131:4758606c9316 167 found = pico_tree_findKey(&DHCPCookies, &test);
TASS Belgium NV 131:4758606c9316 168 if (found)
TASS Belgium NV 131:4758606c9316 169 return found;
TASS Belgium NV 131:4758606c9316 170 else
TASS Belgium NV 131:4758606c9316 171 return NULL;
tass 68:0847e35d08a6 172 }
tass 68:0847e35d08a6 173
tass 152:a3d286bf94e5 174 static void pico_dhcp_client_timer_handler(pico_time now, void *arg);
tass 152:a3d286bf94e5 175 static void pico_dhcp_client_reinit(pico_time now, void *arg);
tass 152:a3d286bf94e5 176 static struct dhcp_client_timer *pico_dhcp_timer_add(uint8_t type, uint32_t time, struct pico_dhcp_client_cookie *ck)
tass 68:0847e35d08a6 177 {
tass 152:a3d286bf94e5 178 struct dhcp_client_timer *t;
tass 68:0847e35d08a6 179
tass 152:a3d286bf94e5 180 t = PICO_ZALLOC(sizeof(struct dhcp_client_timer));
tass 152:a3d286bf94e5 181 if (!t)
tass 152:a3d286bf94e5 182 return NULL;
tass 152:a3d286bf94e5 183
tass 152:a3d286bf94e5 184 t->state = DHCP_CLIENT_TIMER_STARTED;
tass 152:a3d286bf94e5 185 t->xid = ck->xid;
tass 152:a3d286bf94e5 186 t->type = type;
tass 152:a3d286bf94e5 187 pico_timer_add(time, pico_dhcp_client_timer_handler, t);
tass 152:a3d286bf94e5 188 if (ck->timer[type]) {
tass 152:a3d286bf94e5 189 ck->timer[type]->state = DHCP_CLIENT_TIMER_STOPPED;
TASS Belgium NV 131:4758606c9316 190 }
TASS Belgium NV 131:4758606c9316 191
tass 152:a3d286bf94e5 192 ck->timer[type] = t;
tass 152:a3d286bf94e5 193 return t;
tass 68:0847e35d08a6 194 }
tass 68:0847e35d08a6 195
tass 152:a3d286bf94e5 196 static int dhcp_get_timer_event(struct pico_dhcp_client_cookie *dhcpc, unsigned int type)
tass 68:0847e35d08a6 197 {
tass 152:a3d286bf94e5 198 const int events[PICO_DHCPC_TIMER_ARRAY_SIZE] =
tass 152:a3d286bf94e5 199 {
tass 152:a3d286bf94e5 200 PICO_DHCP_EVENT_RETRANSMIT,
tass 152:a3d286bf94e5 201 PICO_DHCP_EVENT_RETRANSMIT,
tass 152:a3d286bf94e5 202 PICO_DHCP_EVENT_RETRANSMIT,
tass 152:a3d286bf94e5 203 PICO_DHCP_EVENT_RETRANSMIT,
tass 152:a3d286bf94e5 204 PICO_DHCP_EVENT_T1,
tass 152:a3d286bf94e5 205 PICO_DHCP_EVENT_T2,
tass 152:a3d286bf94e5 206 PICO_DHCP_EVENT_LEASE
tass 152:a3d286bf94e5 207 };
tass 68:0847e35d08a6 208
tass 152:a3d286bf94e5 209 if (type == PICO_DHCPC_TIMER_REQUEST) {
tass 152:a3d286bf94e5 210 if (++dhcpc->retry > DHCP_CLIENT_RETRIES) {
tass 152:a3d286bf94e5 211 reset(dhcpc, NULL);
tass 152:a3d286bf94e5 212 return PICO_DHCP_EVENT_NONE;
tass 152:a3d286bf94e5 213 }
tass 152:a3d286bf94e5 214 } else if (type < PICO_DHCPC_TIMER_T1) {
tass 152:a3d286bf94e5 215 dhcpc->retry++;
tass 152:a3d286bf94e5 216 }
tass 152:a3d286bf94e5 217
tass 152:a3d286bf94e5 218 return events[type];
tass 152:a3d286bf94e5 219 }
tass 152:a3d286bf94e5 220
tass 152:a3d286bf94e5 221 static void pico_dhcp_client_timer_handler(pico_time now, void *arg)
tass 152:a3d286bf94e5 222 {
tass 152:a3d286bf94e5 223 struct dhcp_client_timer *t = (struct dhcp_client_timer *)arg;
tass 152:a3d286bf94e5 224 struct pico_dhcp_client_cookie *dhcpc;
tass 152:a3d286bf94e5 225
tass 152:a3d286bf94e5 226 if (!t)
TASS Belgium NV 131:4758606c9316 227 return;
tass 68:0847e35d08a6 228
tass 152:a3d286bf94e5 229 (void) now;
tass 152:a3d286bf94e5 230 if (t->state != DHCP_CLIENT_TIMER_STOPPED) {
tass 152:a3d286bf94e5 231 dhcpc = pico_dhcp_client_find_cookie(t->xid);
tass 152:a3d286bf94e5 232 if (dhcpc && dhcpc->timer) {
tass 152:a3d286bf94e5 233 t->state = DHCP_CLIENT_TIMER_STOPPED;
tass 152:a3d286bf94e5 234 if ((t->type == PICO_DHCPC_TIMER_INIT) && (dhcpc->state < DHCP_CLIENT_STATE_SELECTING)) {
tass 152:a3d286bf94e5 235 pico_dhcp_client_reinit(now, dhcpc);
tass 152:a3d286bf94e5 236 } else if (t->type != PICO_DHCPC_TIMER_INIT) {
tass 152:a3d286bf94e5 237 dhcpc->event = (uint8_t)dhcp_get_timer_event(dhcpc, t->type);
tass 152:a3d286bf94e5 238 if (dhcpc->event != PICO_DHCP_EVENT_NONE)
tass 152:a3d286bf94e5 239 pico_dhcp_state_machine(dhcpc->event, dhcpc, NULL);
tass 152:a3d286bf94e5 240 }
tass 152:a3d286bf94e5 241 }
TASS Belgium NV 131:4758606c9316 242 }
tass 68:0847e35d08a6 243 }
tass 68:0847e35d08a6 244
tass 152:a3d286bf94e5 245 static void pico_dhcp_client_timer_stop(struct pico_dhcp_client_cookie *dhcpc, int type)
tass 68:0847e35d08a6 246 {
tass 152:a3d286bf94e5 247 if (dhcpc->timer[type]) {
tass 152:a3d286bf94e5 248 dhcpc->timer[type]->state = DHCP_CLIENT_TIMER_STOPPED;
tass 152:a3d286bf94e5 249 }
tass 68:0847e35d08a6 250
tass 68:0847e35d08a6 251 }
tass 68:0847e35d08a6 252
tass 152:a3d286bf94e5 253
tass 152:a3d286bf94e5 254 static void pico_dhcp_client_reinit(pico_time now, void *arg)
tass 68:0847e35d08a6 255 {
TASS Belgium NV 131:4758606c9316 256 struct pico_dhcp_client_cookie *dhcpc = (struct pico_dhcp_client_cookie *)arg;
tass 152:a3d286bf94e5 257 (void) now;
tass 68:0847e35d08a6 258
tass 152:a3d286bf94e5 259 if (dhcpc->s) {
tass 152:a3d286bf94e5 260 pico_socket_close(dhcpc->s);
tass 152:a3d286bf94e5 261 dhcpc->s = NULL;
tass 152:a3d286bf94e5 262 }
tass 68:0847e35d08a6 263
TASS Belgium NV 131:4758606c9316 264 if (++dhcpc->retry > DHCP_CLIENT_RETRIES) {
TASS Belgium NV 131:4758606c9316 265 pico_err = PICO_ERR_EAGAIN;
tass 152:a3d286bf94e5 266 if (dhcpc->cb)
tass 152:a3d286bf94e5 267 dhcpc->cb(dhcpc, PICO_DHCP_ERROR);
tass 152:a3d286bf94e5 268
TASS Belgium NV 131:4758606c9316 269 pico_dhcp_client_del_cookie(dhcpc->xid);
TASS Belgium NV 131:4758606c9316 270 return;
TASS Belgium NV 131:4758606c9316 271 }
TASS Belgium NV 131:4758606c9316 272
TASS Belgium NV 131:4758606c9316 273 pico_dhcp_client_init(dhcpc);
tass 68:0847e35d08a6 274 return;
tass 68:0847e35d08a6 275 }
tass 68:0847e35d08a6 276
tass 152:a3d286bf94e5 277
tass 68:0847e35d08a6 278 static void pico_dhcp_client_stop_timers(struct pico_dhcp_client_cookie *dhcpc)
tass 68:0847e35d08a6 279 {
tass 152:a3d286bf94e5 280 int i;
TASS Belgium NV 131:4758606c9316 281 dhcpc->retry = 0;
tass 152:a3d286bf94e5 282 for (i = 0; i < PICO_DHCPC_TIMER_ARRAY_SIZE; i++)
tass 152:a3d286bf94e5 283 pico_dhcp_client_timer_stop(dhcpc, i);
tass 68:0847e35d08a6 284 }
tass 68:0847e35d08a6 285
tass 68:0847e35d08a6 286 static void pico_dhcp_client_start_init_timer(struct pico_dhcp_client_cookie *dhcpc)
tass 68:0847e35d08a6 287 {
TASS Belgium NV 131:4758606c9316 288 uint32_t time = 0;
TASS Belgium NV 131:4758606c9316 289 /* timer value is doubled with every retry (exponential backoff) */
tass 152:a3d286bf94e5 290 time = (uint32_t) (DHCP_CLIENT_RETRANS << dhcpc->retry);
tass 152:a3d286bf94e5 291 pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, time * 1000, dhcpc);
tass 68:0847e35d08a6 292 }
tass 68:0847e35d08a6 293
tass 68:0847e35d08a6 294 static void pico_dhcp_client_start_requesting_timer(struct pico_dhcp_client_cookie *dhcpc)
tass 68:0847e35d08a6 295 {
TASS Belgium NV 131:4758606c9316 296 uint32_t time = 0;
tass 68:0847e35d08a6 297
TASS Belgium NV 131:4758606c9316 298 /* timer value is doubled with every retry (exponential backoff) */
tass 152:a3d286bf94e5 299 time = (uint32_t)(DHCP_CLIENT_RETRANS << dhcpc->retry);
tass 152:a3d286bf94e5 300 pico_dhcp_timer_add(PICO_DHCPC_TIMER_REQUEST, time * 1000, dhcpc);
tass 68:0847e35d08a6 301 }
tass 68:0847e35d08a6 302
tass 68:0847e35d08a6 303 static void pico_dhcp_client_start_renewing_timer(struct pico_dhcp_client_cookie *dhcpc)
tass 68:0847e35d08a6 304 {
TASS Belgium NV 131:4758606c9316 305 uint32_t halftime = 0;
tass 68:0847e35d08a6 306
TASS Belgium NV 131:4758606c9316 307 /* wait one-half of the remaining time until T2, down to a minimum of 60 seconds */
TASS Belgium NV 131:4758606c9316 308 /* (dhcpc->retry + 1): initial -> divide by 2, 1st retry -> divide by 4, 2nd retry -> divide by 8, etc */
tass 152:a3d286bf94e5 309 pico_dhcp_client_stop_timers(dhcpc);
tass 152:a3d286bf94e5 310 halftime = dhcpc->renew_time >> (dhcpc->retry + 1);
TASS Belgium NV 131:4758606c9316 311 if (halftime < 60)
TASS Belgium NV 131:4758606c9316 312 halftime = 60;
tass 68:0847e35d08a6 313
tass 152:a3d286bf94e5 314 pico_dhcp_timer_add(PICO_DHCPC_TIMER_RENEW, halftime * 1000, dhcpc);
TASS Belgium NV 131:4758606c9316 315
TASS Belgium NV 131:4758606c9316 316 return;
tass 68:0847e35d08a6 317 }
tass 68:0847e35d08a6 318
tass 68:0847e35d08a6 319 static void pico_dhcp_client_start_rebinding_timer(struct pico_dhcp_client_cookie *dhcpc)
tass 68:0847e35d08a6 320 {
TASS Belgium NV 131:4758606c9316 321 uint32_t halftime = 0;
tass 68:0847e35d08a6 322
tass 152:a3d286bf94e5 323 pico_dhcp_client_stop_timers(dhcpc);
tass 152:a3d286bf94e5 324 halftime = dhcpc->rebind_time >> (dhcpc->retry + 1);
TASS Belgium NV 131:4758606c9316 325 if (halftime < 60)
TASS Belgium NV 131:4758606c9316 326 halftime = 60;
tass 68:0847e35d08a6 327
tass 152:a3d286bf94e5 328 pico_dhcp_timer_add(PICO_DHCPC_TIMER_REBIND, halftime * 1000, dhcpc);
TASS Belgium NV 131:4758606c9316 329
TASS Belgium NV 131:4758606c9316 330 return;
tass 68:0847e35d08a6 331 }
tass 68:0847e35d08a6 332
tass 68:0847e35d08a6 333 static void pico_dhcp_client_start_reacquisition_timers(struct pico_dhcp_client_cookie *dhcpc)
tass 68:0847e35d08a6 334 {
tass 68:0847e35d08a6 335
tass 152:a3d286bf94e5 336 pico_dhcp_client_stop_timers(dhcpc);
tass 152:a3d286bf94e5 337 pico_dhcp_timer_add(PICO_DHCPC_TIMER_T1, dhcpc->t1_time * 1000, dhcpc);
tass 152:a3d286bf94e5 338 pico_dhcp_timer_add(PICO_DHCPC_TIMER_T2, dhcpc->t2_time * 1000, dhcpc);
tass 152:a3d286bf94e5 339 pico_dhcp_timer_add(PICO_DHCPC_TIMER_LEASE, dhcpc->lease_time * 1000, dhcpc);
tass 68:0847e35d08a6 340 }
tass 68:0847e35d08a6 341
tass 68:0847e35d08a6 342 static int pico_dhcp_client_init(struct pico_dhcp_client_cookie *dhcpc)
tass 68:0847e35d08a6 343 {
TASS Belgium NV 131:4758606c9316 344 uint16_t port = PICO_DHCP_CLIENT_PORT;
tass 152:a3d286bf94e5 345 if (!dhcpc)
tass 152:a3d286bf94e5 346 return -1;
tass 68:0847e35d08a6 347
tass 152:a3d286bf94e5 348 /* adding a link with address 0.0.0.0 and netmask 0.0.0.0,
tass 152:a3d286bf94e5 349 * automatically adds a route for a global broadcast */
tass 152:a3d286bf94e5 350 pico_ipv4_link_add(dhcpc->dev, inaddr_any, bcast_netmask);
tass 152:a3d286bf94e5 351 if (!dhcpc->s)
tass 152:a3d286bf94e5 352 dhcpc->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcp_client_wakeup);
tass 152:a3d286bf94e5 353
tass 152:a3d286bf94e5 354 if (!dhcpc->s) {
tass 152:a3d286bf94e5 355 pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc);
TASS Belgium NV 131:4758606c9316 356 return 0;
TASS Belgium NV 131:4758606c9316 357 }
tass 68:0847e35d08a6 358
tass 152:a3d286bf94e5 359 dhcpc->s->dev = dhcpc->dev;
tass 152:a3d286bf94e5 360 if (pico_socket_bind(dhcpc->s, &inaddr_any, &port) < 0) {
tass 152:a3d286bf94e5 361 pico_socket_close(dhcpc->s);
tass 152:a3d286bf94e5 362 dhcpc->s = NULL;
tass 152:a3d286bf94e5 363 pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc);
tass 152:a3d286bf94e5 364 return 0;
tass 152:a3d286bf94e5 365 }
tass 68:0847e35d08a6 366
tass 152:a3d286bf94e5 367 if (pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_DISCOVER) < 0) {
tass 152:a3d286bf94e5 368 pico_socket_close(dhcpc->s);
tass 152:a3d286bf94e5 369 dhcpc->s = NULL;
tass 152:a3d286bf94e5 370 pico_dhcp_timer_add(PICO_DHCPC_TIMER_INIT, DHCP_CLIENT_REINIT, dhcpc);
tass 152:a3d286bf94e5 371 return 0;
tass 152:a3d286bf94e5 372 }
tass 68:0847e35d08a6 373
tass 152:a3d286bf94e5 374 dhcpc->retry = 0;
tass 152:a3d286bf94e5 375 dhcpc->init_timestamp = PICO_TIME_MS();
tass 152:a3d286bf94e5 376 pico_dhcp_client_start_init_timer(dhcpc);
TASS Belgium NV 131:4758606c9316 377 return 0;
tass 68:0847e35d08a6 378 }
tass 68:0847e35d08a6 379
tass 68:0847e35d08a6 380 int pico_dhcp_initiate_negotiation(struct pico_device *dev, void (*cb)(void *dhcpc, int code), uint32_t *uid)
tass 68:0847e35d08a6 381 {
TASS Belgium NV 131:4758606c9316 382 uint8_t retry = 32;
TASS Belgium NV 131:4758606c9316 383 uint32_t xid = 0;
TASS Belgium NV 131:4758606c9316 384 struct pico_dhcp_client_cookie *dhcpc = NULL;
tass 68:0847e35d08a6 385
TASS Belgium NV 131:4758606c9316 386 if (!dev || !cb || !uid) {
TASS Belgium NV 131:4758606c9316 387 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 388 return -1;
TASS Belgium NV 131:4758606c9316 389 }
TASS Belgium NV 131:4758606c9316 390
TASS Belgium NV 131:4758606c9316 391 if (!dev->eth) {
TASS Belgium NV 131:4758606c9316 392 pico_err = PICO_ERR_EOPNOTSUPP;
TASS Belgium NV 131:4758606c9316 393 return -1;
TASS Belgium NV 131:4758606c9316 394 }
tass 68:0847e35d08a6 395
TASS Belgium NV 131:4758606c9316 396 /* attempt to generate a correct xid, else fail */
TASS Belgium NV 131:4758606c9316 397 do {
TASS Belgium NV 131:4758606c9316 398 xid = pico_rand();
TASS Belgium NV 131:4758606c9316 399 } while (!xid && --retry);
tass 68:0847e35d08a6 400
TASS Belgium NV 131:4758606c9316 401 if (!xid) {
TASS Belgium NV 131:4758606c9316 402 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 403 return -1;
TASS Belgium NV 131:4758606c9316 404 }
tass 68:0847e35d08a6 405
TASS Belgium NV 131:4758606c9316 406 dhcpc = pico_dhcp_client_add_cookie(xid, dev, cb, uid);
TASS Belgium NV 131:4758606c9316 407 if (!dhcpc)
TASS Belgium NV 131:4758606c9316 408 return -1;
tass 68:0847e35d08a6 409
TASS Belgium NV 131:4758606c9316 410 dhcpc_dbg("DHCP client: cookie with xid %u\n", dhcpc->xid);
tass 152:a3d286bf94e5 411 *uid = xid;
TASS Belgium NV 131:4758606c9316 412 return pico_dhcp_client_init(dhcpc);
tass 68:0847e35d08a6 413 }
tass 68:0847e35d08a6 414
tass 68:0847e35d08a6 415 static void pico_dhcp_client_recv_params(struct pico_dhcp_client_cookie *dhcpc, struct pico_dhcp_opt *opt)
tass 68:0847e35d08a6 416 {
TASS Belgium NV 131:4758606c9316 417 do {
TASS Belgium NV 131:4758606c9316 418 switch (opt->code)
TASS Belgium NV 131:4758606c9316 419 {
TASS Belgium NV 131:4758606c9316 420 case PICO_DHCP_OPT_PAD:
TASS Belgium NV 131:4758606c9316 421 break;
tass 68:0847e35d08a6 422
TASS Belgium NV 131:4758606c9316 423 case PICO_DHCP_OPT_END:
TASS Belgium NV 131:4758606c9316 424 break;
tass 68:0847e35d08a6 425
TASS Belgium NV 131:4758606c9316 426 case PICO_DHCP_OPT_MSGTYPE:
TASS Belgium NV 131:4758606c9316 427 dhcpc->event = opt->ext.msg_type.type;
TASS Belgium NV 131:4758606c9316 428 dhcpc_dbg("DHCP client: message type %u\n", dhcpc->event);
TASS Belgium NV 131:4758606c9316 429 break;
tass 68:0847e35d08a6 430
TASS Belgium NV 131:4758606c9316 431 case PICO_DHCP_OPT_LEASETIME:
tass 152:a3d286bf94e5 432 dhcpc->lease_time = long_be(opt->ext.lease_time.time);
tass 152:a3d286bf94e5 433 dhcpc_dbg("DHCP client: lease time %u\n", dhcpc->lease_time);
TASS Belgium NV 131:4758606c9316 434 break;
TASS Belgium NV 131:4758606c9316 435
TASS Belgium NV 131:4758606c9316 436 case PICO_DHCP_OPT_RENEWALTIME:
tass 152:a3d286bf94e5 437 dhcpc->t1_time = long_be(opt->ext.renewal_time.time);
tass 152:a3d286bf94e5 438 dhcpc_dbg("DHCP client: renewal time %u\n", dhcpc->t1_time);
TASS Belgium NV 131:4758606c9316 439 break;
tass 68:0847e35d08a6 440
TASS Belgium NV 131:4758606c9316 441 case PICO_DHCP_OPT_REBINDINGTIME:
tass 152:a3d286bf94e5 442 dhcpc->t2_time = long_be(opt->ext.rebinding_time.time);
tass 152:a3d286bf94e5 443 dhcpc_dbg("DHCP client: rebinding time %u\n", dhcpc->t2_time);
TASS Belgium NV 131:4758606c9316 444 break;
tass 68:0847e35d08a6 445
TASS Belgium NV 131:4758606c9316 446 case PICO_DHCP_OPT_ROUTER:
TASS Belgium NV 131:4758606c9316 447 dhcpc->gateway = opt->ext.router.ip;
TASS Belgium NV 131:4758606c9316 448 dhcpc_dbg("DHCP client: router %08X\n", dhcpc->gateway.addr);
TASS Belgium NV 131:4758606c9316 449 break;
tass 68:0847e35d08a6 450
TASS Belgium NV 131:4758606c9316 451 case PICO_DHCP_OPT_DNS:
tass 152:a3d286bf94e5 452 dhcpc->nameserver[0] = opt->ext.dns1.ip;
tass 152:a3d286bf94e5 453 dhcpc_dbg("DHCP client: dns1 %08X\n", dhcpc->nameserver[0].addr);
tass 152:a3d286bf94e5 454 if (opt->len >= 8) {
tass 152:a3d286bf94e5 455 dhcpc->nameserver[1] = opt->ext.dns2.ip;
tass 152:a3d286bf94e5 456 dhcpc_dbg("DHCP client: dns1 %08X\n", dhcpc->nameserver[1].addr);
tass 152:a3d286bf94e5 457 }
tass 152:a3d286bf94e5 458
TASS Belgium NV 131:4758606c9316 459 break;
tass 68:0847e35d08a6 460
TASS Belgium NV 131:4758606c9316 461 case PICO_DHCP_OPT_NETMASK:
TASS Belgium NV 131:4758606c9316 462 dhcpc->netmask = opt->ext.netmask.ip;
TASS Belgium NV 131:4758606c9316 463 dhcpc_dbg("DHCP client: netmask %08X\n", dhcpc->netmask.addr);
TASS Belgium NV 131:4758606c9316 464 break;
tass 68:0847e35d08a6 465
TASS Belgium NV 131:4758606c9316 466 case PICO_DHCP_OPT_SERVERID:
TASS Belgium NV 131:4758606c9316 467 dhcpc->server_id = opt->ext.server_id.ip;
TASS Belgium NV 131:4758606c9316 468 dhcpc_dbg("DHCP client: server ID %08X\n", dhcpc->server_id.addr);
TASS Belgium NV 131:4758606c9316 469 break;
tass 68:0847e35d08a6 470
TASS Belgium NV 131:4758606c9316 471 case PICO_DHCP_OPT_OPTOVERLOAD:
TASS Belgium NV 131:4758606c9316 472 dhcpc_dbg("DHCP client: WARNING option overload present (not processed)");
TASS Belgium NV 131:4758606c9316 473 break;
tass 68:0847e35d08a6 474
TASS Belgium NV 131:4758606c9316 475 default:
TASS Belgium NV 131:4758606c9316 476 dhcpc_dbg("DHCP client: WARNING unsupported option %u\n", opt->code);
TASS Belgium NV 131:4758606c9316 477 break;
TASS Belgium NV 131:4758606c9316 478 }
TASS Belgium NV 131:4758606c9316 479 } while (pico_dhcp_next_option(&opt));
tass 68:0847e35d08a6 480
TASS Belgium NV 131:4758606c9316 481 /* default values for T1 and T2 when not provided */
tass 152:a3d286bf94e5 482 if (!dhcpc->t1_time)
tass 152:a3d286bf94e5 483 dhcpc->t1_time = dhcpc->lease_time >> 1;
tass 68:0847e35d08a6 484
tass 152:a3d286bf94e5 485 if (!dhcpc->t2_time)
tass 152:a3d286bf94e5 486 dhcpc->t2_time = (dhcpc->lease_time * 875) / 1000;
TASS Belgium NV 131:4758606c9316 487
TASS Belgium NV 131:4758606c9316 488 return;
tass 68:0847e35d08a6 489 }
tass 68:0847e35d08a6 490
tass 68:0847e35d08a6 491 static int recv_offer(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
tass 68:0847e35d08a6 492 {
TASS Belgium NV 131:4758606c9316 493 struct pico_dhcp_hdr *hdr = (struct pico_dhcp_hdr *)buf;
tass 154:6c0e92a80c4a 494 struct pico_dhcp_opt *opt = DHCP_OPT(hdr,0);
TASS Belgium NV 131:4758606c9316 495
TASS Belgium NV 131:4758606c9316 496 pico_dhcp_client_recv_params(dhcpc, opt);
tass 152:a3d286bf94e5 497 if ((dhcpc->event != PICO_DHCP_MSG_OFFER) || !dhcpc->server_id.addr || !dhcpc->netmask.addr || !dhcpc->lease_time)
TASS Belgium NV 131:4758606c9316 498 return -1;
tass 68:0847e35d08a6 499
TASS Belgium NV 131:4758606c9316 500 dhcpc->address.addr = hdr->yiaddr;
tass 68:0847e35d08a6 501
TASS Belgium NV 131:4758606c9316 502 /* we skip state SELECTING, process first offer received */
TASS Belgium NV 131:4758606c9316 503 dhcpc->state = DHCP_CLIENT_STATE_REQUESTING;
TASS Belgium NV 131:4758606c9316 504 dhcpc->retry = 0;
TASS Belgium NV 131:4758606c9316 505 pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
TASS Belgium NV 131:4758606c9316 506 pico_dhcp_client_start_requesting_timer(dhcpc);
TASS Belgium NV 131:4758606c9316 507 return 0;
tass 68:0847e35d08a6 508 }
tass 68:0847e35d08a6 509
tass 68:0847e35d08a6 510 static int recv_ack(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
tass 68:0847e35d08a6 511 {
TASS Belgium NV 131:4758606c9316 512 struct pico_dhcp_hdr *hdr = (struct pico_dhcp_hdr *)buf;
tass 154:6c0e92a80c4a 513 struct pico_dhcp_opt *opt = DHCP_OPT(hdr,0);
TASS Belgium NV 131:4758606c9316 514 struct pico_ip4 address = {
TASS Belgium NV 131:4758606c9316 515 0
tass 152:a3d286bf94e5 516 };
tass 152:a3d286bf94e5 517 struct pico_ip4 any_address = {
TASS Belgium NV 131:4758606c9316 518 0
TASS Belgium NV 131:4758606c9316 519 };
tass 68:0847e35d08a6 520
tass 152:a3d286bf94e5 521 struct pico_ipv4_link *l;
tass 152:a3d286bf94e5 522
TASS Belgium NV 131:4758606c9316 523 pico_dhcp_client_recv_params(dhcpc, opt);
tass 152:a3d286bf94e5 524 if ((dhcpc->event != PICO_DHCP_MSG_ACK) || !dhcpc->server_id.addr || !dhcpc->netmask.addr || !dhcpc->lease_time)
TASS Belgium NV 131:4758606c9316 525 return -1;
tass 68:0847e35d08a6 526
TASS Belgium NV 131:4758606c9316 527 /* Issue #20 the server can transmit on ACK a different IP than the one in OFFER */
TASS Belgium NV 131:4758606c9316 528 /* RFC2131 ch 4.3.2 ... The client SHOULD use the parameters in the DHCPACK message for configuration */
TASS Belgium NV 131:4758606c9316 529 if (dhcpc->state == DHCP_CLIENT_STATE_REQUESTING)
TASS Belgium NV 131:4758606c9316 530 dhcpc->address.addr = hdr->yiaddr;
tass 73:dfb737147f6e 531
tass 73:dfb737147f6e 532
TASS Belgium NV 131:4758606c9316 533 /* close the socket used for address (re)acquisition */
TASS Belgium NV 131:4758606c9316 534 pico_socket_close(dhcpc->s);
tass 152:a3d286bf94e5 535 dhcpc->s = NULL;
tass 152:a3d286bf94e5 536
tass 152:a3d286bf94e5 537 /* Delete all the links before adding the address */
tass 152:a3d286bf94e5 538 pico_ipv4_link_del(dhcpc->dev, address);
tass 152:a3d286bf94e5 539 l = pico_ipv4_link_by_dev(dhcpc->dev);
tass 152:a3d286bf94e5 540 while(l) {
tass 152:a3d286bf94e5 541 pico_ipv4_link_del(dhcpc->dev, l->address);
tass 152:a3d286bf94e5 542 l = pico_ipv4_link_by_dev_next(dhcpc->dev, l);
tass 152:a3d286bf94e5 543 }
tass 152:a3d286bf94e5 544 pico_ipv4_link_add(dhcpc->dev, dhcpc->address, dhcpc->netmask);
tass 152:a3d286bf94e5 545
tass 152:a3d286bf94e5 546 dbg("DHCP client: renewal time (T1) %u\n", (unsigned int)dhcpc->t1_time);
tass 152:a3d286bf94e5 547 dbg("DHCP client: rebinding time (T2) %u\n", (unsigned int)dhcpc->t2_time);
tass 152:a3d286bf94e5 548 dbg("DHCP client: lease time %u\n", (unsigned int)dhcpc->lease_time);
tass 152:a3d286bf94e5 549
tass 152:a3d286bf94e5 550 /* If router option is received, use it as default gateway */
tass 152:a3d286bf94e5 551 if (dhcpc->gateway.addr != 0U) {
tass 152:a3d286bf94e5 552 pico_ipv4_route_add(any_address, any_address, dhcpc->gateway, 1, NULL);
TASS Belgium NV 131:4758606c9316 553 }
TASS Belgium NV 131:4758606c9316 554
TASS Belgium NV 131:4758606c9316 555 dhcpc->retry = 0;
tass 152:a3d286bf94e5 556 dhcpc->renew_time = dhcpc->t2_time - dhcpc->t1_time;
tass 152:a3d286bf94e5 557 dhcpc->rebind_time = dhcpc->lease_time - dhcpc->t2_time;
TASS Belgium NV 131:4758606c9316 558 pico_dhcp_client_start_reacquisition_timers(dhcpc);
tass 68:0847e35d08a6 559
TASS Belgium NV 131:4758606c9316 560 *(dhcpc->uid) = dhcpc->xid;
tass 152:a3d286bf94e5 561 if (dhcpc->cb)
tass 152:a3d286bf94e5 562 dhcpc->cb(dhcpc, PICO_DHCP_SUCCESS);
tass 152:a3d286bf94e5 563
TASS Belgium NV 131:4758606c9316 564 dhcpc->state = DHCP_CLIENT_STATE_BOUND;
TASS Belgium NV 131:4758606c9316 565 return 0;
tass 68:0847e35d08a6 566 }
tass 68:0847e35d08a6 567
tass 152:a3d286bf94e5 568 static int renew(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
tass 68:0847e35d08a6 569 {
TASS Belgium NV 131:4758606c9316 570 uint16_t port = PICO_DHCP_CLIENT_PORT;
tass 152:a3d286bf94e5 571 (void) buf;
TASS Belgium NV 131:4758606c9316 572 dhcpc->state = DHCP_CLIENT_STATE_RENEWING;
TASS Belgium NV 131:4758606c9316 573 dhcpc->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcp_client_wakeup);
TASS Belgium NV 131:4758606c9316 574 if (!dhcpc->s) {
TASS Belgium NV 131:4758606c9316 575 dhcpc_dbg("DHCP client ERROR: failure opening socket on renew, aborting DHCP! (%s)\n", strerror(pico_err));
tass 152:a3d286bf94e5 576 if (dhcpc->cb)
tass 152:a3d286bf94e5 577 dhcpc->cb(dhcpc, PICO_DHCP_ERROR);
tass 152:a3d286bf94e5 578
TASS Belgium NV 131:4758606c9316 579 return -1;
TASS Belgium NV 131:4758606c9316 580 }
tass 68:0847e35d08a6 581
TASS Belgium NV 131:4758606c9316 582 if (pico_socket_bind(dhcpc->s, &dhcpc->address, &port) != 0) {
TASS Belgium NV 131:4758606c9316 583 dhcpc_dbg("DHCP client ERROR: failure binding socket on renew, aborting DHCP! (%s)\n", strerror(pico_err));
TASS Belgium NV 131:4758606c9316 584 pico_socket_close(dhcpc->s);
tass 152:a3d286bf94e5 585 dhcpc->s = NULL;
tass 152:a3d286bf94e5 586 if (dhcpc->cb)
tass 152:a3d286bf94e5 587 dhcpc->cb(dhcpc, PICO_DHCP_ERROR);
tass 152:a3d286bf94e5 588
TASS Belgium NV 131:4758606c9316 589 return -1;
TASS Belgium NV 131:4758606c9316 590 }
tass 68:0847e35d08a6 591
TASS Belgium NV 131:4758606c9316 592 dhcpc->retry = 0;
TASS Belgium NV 131:4758606c9316 593 pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
TASS Belgium NV 131:4758606c9316 594 pico_dhcp_client_start_renewing_timer(dhcpc);
tass 68:0847e35d08a6 595
TASS Belgium NV 131:4758606c9316 596 return 0;
tass 68:0847e35d08a6 597 }
tass 68:0847e35d08a6 598
tass 152:a3d286bf94e5 599 static int rebind(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
tass 68:0847e35d08a6 600 {
tass 152:a3d286bf94e5 601 (void) buf;
tass 68:0847e35d08a6 602
TASS Belgium NV 131:4758606c9316 603 dhcpc->state = DHCP_CLIENT_STATE_REBINDING;
TASS Belgium NV 131:4758606c9316 604 dhcpc->retry = 0;
TASS Belgium NV 131:4758606c9316 605 pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
TASS Belgium NV 131:4758606c9316 606 pico_dhcp_client_start_rebinding_timer(dhcpc);
tass 68:0847e35d08a6 607
TASS Belgium NV 131:4758606c9316 608 return 0;
tass 68:0847e35d08a6 609 }
tass 68:0847e35d08a6 610
tass 152:a3d286bf94e5 611 static int reset(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
tass 68:0847e35d08a6 612 {
TASS Belgium NV 131:4758606c9316 613 struct pico_ip4 address = {
TASS Belgium NV 131:4758606c9316 614 0
TASS Belgium NV 131:4758606c9316 615 };
tass 152:a3d286bf94e5 616 (void) buf;
tass 68:0847e35d08a6 617
TASS Belgium NV 131:4758606c9316 618 if (dhcpc->state == DHCP_CLIENT_STATE_REQUESTING)
TASS Belgium NV 131:4758606c9316 619 address.addr = PICO_IP4_ANY;
TASS Belgium NV 131:4758606c9316 620 else
TASS Belgium NV 131:4758606c9316 621 address.addr = dhcpc->address.addr;
tass 68:0847e35d08a6 622
TASS Belgium NV 131:4758606c9316 623 /* close the socket used for address (re)acquisition */
TASS Belgium NV 131:4758606c9316 624 pico_socket_close(dhcpc->s);
tass 152:a3d286bf94e5 625 dhcpc->s = NULL;
TASS Belgium NV 131:4758606c9316 626 /* delete the link with the currently in use address */
TASS Belgium NV 131:4758606c9316 627 pico_ipv4_link_del(dhcpc->dev, address);
tass 68:0847e35d08a6 628
tass 152:a3d286bf94e5 629 if (dhcpc->cb)
tass 152:a3d286bf94e5 630 dhcpc->cb(dhcpc, PICO_DHCP_RESET);
tass 152:a3d286bf94e5 631
TASS Belgium NV 131:4758606c9316 632 if (dhcpc->state < DHCP_CLIENT_STATE_BOUND)
TASS Belgium NV 131:4758606c9316 633 {
tass 152:a3d286bf94e5 634 /* pico_dhcp_client_timer_stop(dhcpc, PICO_DHCPC_TIMER_INIT); */
TASS Belgium NV 131:4758606c9316 635 }
TASS Belgium NV 131:4758606c9316 636
tass 152:a3d286bf94e5 637
TASS Belgium NV 131:4758606c9316 638 dhcpc->state = DHCP_CLIENT_STATE_INIT;
TASS Belgium NV 131:4758606c9316 639 pico_dhcp_client_stop_timers(dhcpc);
TASS Belgium NV 131:4758606c9316 640 pico_dhcp_client_init(dhcpc);
TASS Belgium NV 131:4758606c9316 641 return 0;
tass 68:0847e35d08a6 642 }
tass 68:0847e35d08a6 643
tass 152:a3d286bf94e5 644 static int retransmit(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
tass 68:0847e35d08a6 645 {
tass 152:a3d286bf94e5 646 (void) buf;
TASS Belgium NV 131:4758606c9316 647 switch (dhcpc->state)
TASS Belgium NV 131:4758606c9316 648 {
tass 68:0847e35d08a6 649 case DHCP_CLIENT_STATE_INIT:
TASS Belgium NV 131:4758606c9316 650 pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_DISCOVER);
TASS Belgium NV 131:4758606c9316 651 pico_dhcp_client_start_init_timer(dhcpc);
TASS Belgium NV 131:4758606c9316 652 break;
tass 68:0847e35d08a6 653
tass 68:0847e35d08a6 654 case DHCP_CLIENT_STATE_REQUESTING:
TASS Belgium NV 131:4758606c9316 655 pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
TASS Belgium NV 131:4758606c9316 656 pico_dhcp_client_start_requesting_timer(dhcpc);
TASS Belgium NV 131:4758606c9316 657 break;
tass 68:0847e35d08a6 658
tass 68:0847e35d08a6 659 case DHCP_CLIENT_STATE_RENEWING:
TASS Belgium NV 131:4758606c9316 660 pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_REQUEST);
TASS Belgium NV 131:4758606c9316 661 pico_dhcp_client_start_renewing_timer(dhcpc);
TASS Belgium NV 131:4758606c9316 662 break;
tass 68:0847e35d08a6 663
tass 68:0847e35d08a6 664 case DHCP_CLIENT_STATE_REBINDING:
TASS Belgium NV 131:4758606c9316 665 pico_dhcp_client_msg(dhcpc, PICO_DHCP_MSG_DISCOVER);
TASS Belgium NV 131:4758606c9316 666 pico_dhcp_client_start_rebinding_timer(dhcpc);
TASS Belgium NV 131:4758606c9316 667 break;
tass 68:0847e35d08a6 668
tass 68:0847e35d08a6 669 default:
TASS Belgium NV 131:4758606c9316 670 dhcpc_dbg("DHCP client WARNING: retransmit in incorrect state (%u)!\n", dhcpc->state);
TASS Belgium NV 131:4758606c9316 671 return -1;
TASS Belgium NV 131:4758606c9316 672 }
TASS Belgium NV 131:4758606c9316 673 return 0;
tass 68:0847e35d08a6 674 }
tass 68:0847e35d08a6 675
tass 68:0847e35d08a6 676 struct dhcp_action_entry {
TASS Belgium NV 131:4758606c9316 677 int (*offer)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
TASS Belgium NV 131:4758606c9316 678 int (*ack)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
TASS Belgium NV 131:4758606c9316 679 int (*nak)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
TASS Belgium NV 131:4758606c9316 680 int (*timer1)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
TASS Belgium NV 131:4758606c9316 681 int (*timer2)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
TASS Belgium NV 131:4758606c9316 682 int (*timer_lease)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
TASS Belgium NV 131:4758606c9316 683 int (*timer_retransmit)(struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf);
tass 68:0847e35d08a6 684 };
tass 68:0847e35d08a6 685
TASS Belgium NV 131:4758606c9316 686 static struct dhcp_action_entry dhcp_fsm[] =
tass 68:0847e35d08a6 687 { /* event |offer |ack |nak |T1 |T2 |lease |retransmit */
TASS Belgium NV 131:4758606c9316 688 /* state init-reboot */
TASS Belgium NV 131:4758606c9316 689 { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
tass 68:0847e35d08a6 690 /* state rebooting */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
tass 68:0847e35d08a6 691 /* state init */ { recv_offer, NULL, NULL, NULL, NULL, NULL, retransmit },
tass 68:0847e35d08a6 692 /* state selecting */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
tass 68:0847e35d08a6 693 /* state requesting */ { NULL, recv_ack, reset, NULL, NULL, NULL, retransmit },
tass 68:0847e35d08a6 694 /* state bound */ { NULL, NULL, NULL, renew, NULL, NULL, NULL },
tass 68:0847e35d08a6 695 /* state renewing */ { NULL, recv_ack, reset, NULL, rebind, NULL, retransmit },
tass 68:0847e35d08a6 696 /* state rebinding */ { NULL, recv_ack, reset, NULL, NULL, reset, retransmit },
tass 68:0847e35d08a6 697 };
tass 68:0847e35d08a6 698
tass 68:0847e35d08a6 699 /* TIMERS REMARK:
tass 68:0847e35d08a6 700 * In state bound we have T1, T2 and the lease timer running. If T1 goes off, we attempt to renew.
tass 68:0847e35d08a6 701 * If the renew succeeds a new T1, T2 and lease timer is started. The former T2 and lease timer is
TASS Belgium NV 131:4758606c9316 702 * still running though. This poses no concerns as the T2 and lease event in state bound have a NULL
TASS Belgium NV 131:4758606c9316 703 * pointer in the fsm. If the former T2 or lease timer goes off, nothing happens. Same situation
tass 68:0847e35d08a6 704 * applies for T2 and a succesfull rebind. */
tass 68:0847e35d08a6 705
tass 68:0847e35d08a6 706 static void pico_dhcp_state_machine(uint8_t event, struct pico_dhcp_client_cookie *dhcpc, uint8_t *buf)
tass 68:0847e35d08a6 707 {
TASS Belgium NV 131:4758606c9316 708 switch (event)
TASS Belgium NV 131:4758606c9316 709 {
tass 68:0847e35d08a6 710 case PICO_DHCP_MSG_OFFER:
TASS Belgium NV 131:4758606c9316 711 dhcpc_dbg("DHCP client: received OFFER\n");
TASS Belgium NV 131:4758606c9316 712 if (dhcp_fsm[dhcpc->state].offer)
TASS Belgium NV 131:4758606c9316 713 dhcp_fsm[dhcpc->state].offer(dhcpc, buf);
TASS Belgium NV 131:4758606c9316 714
TASS Belgium NV 131:4758606c9316 715 break;
tass 68:0847e35d08a6 716
tass 68:0847e35d08a6 717 case PICO_DHCP_MSG_ACK:
TASS Belgium NV 131:4758606c9316 718 dhcpc_dbg("DHCP client: received ACK\n");
TASS Belgium NV 131:4758606c9316 719 if (dhcp_fsm[dhcpc->state].ack)
TASS Belgium NV 131:4758606c9316 720 dhcp_fsm[dhcpc->state].ack(dhcpc, buf);
TASS Belgium NV 131:4758606c9316 721
TASS Belgium NV 131:4758606c9316 722 break;
tass 68:0847e35d08a6 723
tass 68:0847e35d08a6 724 case PICO_DHCP_MSG_NAK:
TASS Belgium NV 131:4758606c9316 725 dhcpc_dbg("DHCP client: received NAK\n");
TASS Belgium NV 131:4758606c9316 726 if (dhcp_fsm[dhcpc->state].nak)
TASS Belgium NV 131:4758606c9316 727 dhcp_fsm[dhcpc->state].nak(dhcpc, buf);
TASS Belgium NV 131:4758606c9316 728
TASS Belgium NV 131:4758606c9316 729 break;
tass 68:0847e35d08a6 730
tass 68:0847e35d08a6 731 case PICO_DHCP_EVENT_T1:
TASS Belgium NV 131:4758606c9316 732 dhcpc_dbg("DHCP client: received T1 timeout\n");
TASS Belgium NV 131:4758606c9316 733 if (dhcp_fsm[dhcpc->state].timer1)
TASS Belgium NV 131:4758606c9316 734 dhcp_fsm[dhcpc->state].timer1(dhcpc, NULL);
TASS Belgium NV 131:4758606c9316 735
TASS Belgium NV 131:4758606c9316 736 break;
tass 68:0847e35d08a6 737
tass 68:0847e35d08a6 738 case PICO_DHCP_EVENT_T2:
TASS Belgium NV 131:4758606c9316 739 dhcpc_dbg("DHCP client: received T2 timeout\n");
TASS Belgium NV 131:4758606c9316 740 if (dhcp_fsm[dhcpc->state].timer2)
TASS Belgium NV 131:4758606c9316 741 dhcp_fsm[dhcpc->state].timer2(dhcpc, NULL);
TASS Belgium NV 131:4758606c9316 742
TASS Belgium NV 131:4758606c9316 743 break;
tass 68:0847e35d08a6 744
tass 68:0847e35d08a6 745 case PICO_DHCP_EVENT_LEASE:
TASS Belgium NV 131:4758606c9316 746 dhcpc_dbg("DHCP client: received LEASE timeout\n");
TASS Belgium NV 131:4758606c9316 747 if (dhcp_fsm[dhcpc->state].timer_lease)
TASS Belgium NV 131:4758606c9316 748 dhcp_fsm[dhcpc->state].timer_lease(dhcpc, NULL);
TASS Belgium NV 131:4758606c9316 749
TASS Belgium NV 131:4758606c9316 750 break;
tass 68:0847e35d08a6 751
tass 68:0847e35d08a6 752 case PICO_DHCP_EVENT_RETRANSMIT:
TASS Belgium NV 131:4758606c9316 753 dhcpc_dbg("DHCP client: received RETRANSMIT timeout\n");
TASS Belgium NV 131:4758606c9316 754 if (dhcp_fsm[dhcpc->state].timer_retransmit)
TASS Belgium NV 131:4758606c9316 755 dhcp_fsm[dhcpc->state].timer_retransmit(dhcpc, NULL);
TASS Belgium NV 131:4758606c9316 756
TASS Belgium NV 131:4758606c9316 757 break;
tass 68:0847e35d08a6 758
tass 68:0847e35d08a6 759 default:
TASS Belgium NV 131:4758606c9316 760 dhcpc_dbg("DHCP client WARNING: unrecognized event (%u)!\n", dhcpc->event);
TASS Belgium NV 131:4758606c9316 761 return;
TASS Belgium NV 131:4758606c9316 762 }
TASS Belgium NV 131:4758606c9316 763 return;
tass 68:0847e35d08a6 764 }
tass 68:0847e35d08a6 765
tass 70:cd218dd180e5 766 static int16_t pico_dhcp_client_opt_parse(void *ptr, uint16_t len)
tass 68:0847e35d08a6 767 {
TASS Belgium NV 131:4758606c9316 768 uint32_t optlen = len - (uint32_t)sizeof(struct pico_dhcp_hdr);
TASS Belgium NV 131:4758606c9316 769 struct pico_dhcp_hdr *hdr = (struct pico_dhcp_hdr *)ptr;
tass 154:6c0e92a80c4a 770 struct pico_dhcp_opt *opt = DHCP_OPT(hdr,0);
TASS Belgium NV 131:4758606c9316 771
TASS Belgium NV 131:4758606c9316 772 if (hdr->dhcp_magic != PICO_DHCPD_MAGIC_COOKIE)
TASS Belgium NV 131:4758606c9316 773 return -1;
tass 68:0847e35d08a6 774
tass 154:6c0e92a80c4a 775 if (!pico_dhcp_are_options_valid(opt, (int32_t)optlen))
TASS Belgium NV 131:4758606c9316 776 return -1;
TASS Belgium NV 131:4758606c9316 777
TASS Belgium NV 131:4758606c9316 778 do {
TASS Belgium NV 131:4758606c9316 779 if (opt->code == PICO_DHCP_OPT_MSGTYPE)
TASS Belgium NV 131:4758606c9316 780 return opt->ext.msg_type.type;
TASS Belgium NV 131:4758606c9316 781 } while (pico_dhcp_next_option(&opt));
TASS Belgium NV 131:4758606c9316 782
tass 68:0847e35d08a6 783 return -1;
tass 68:0847e35d08a6 784 }
tass 68:0847e35d08a6 785
tass 70:cd218dd180e5 786 static int8_t pico_dhcp_client_msg(struct pico_dhcp_client_cookie *dhcpc, uint8_t msg_type)
tass 68:0847e35d08a6 787 {
TASS Belgium NV 131:4758606c9316 788 int32_t r = 0;
TASS Belgium NV 131:4758606c9316 789 uint16_t optlen = 0, offset = 0;
TASS Belgium NV 131:4758606c9316 790 struct pico_ip4 destination = {
TASS Belgium NV 131:4758606c9316 791 .addr = 0xFFFFFFFF
TASS Belgium NV 131:4758606c9316 792 };
TASS Belgium NV 131:4758606c9316 793 struct pico_dhcp_hdr *hdr = NULL;
tass 68:0847e35d08a6 794
tass 152:a3d286bf94e5 795
tass 152:a3d286bf94e5 796 /* RFC 2131 3.1.3: Request is always BROADCAST */
tass 152:a3d286bf94e5 797
tass 152:a3d286bf94e5 798 /* Set again default route for the bcast request */
tass 152:a3d286bf94e5 799 pico_ipv4_route_set_bcast_link(pico_ipv4_link_by_dev(dhcpc->dev));
tass 152:a3d286bf94e5 800
TASS Belgium NV 131:4758606c9316 801 switch (msg_type)
TASS Belgium NV 131:4758606c9316 802 {
tass 68:0847e35d08a6 803 case PICO_DHCP_MSG_DISCOVER:
TASS Belgium NV 131:4758606c9316 804 dhcpc_dbg("DHCP client: sent DHCPDISCOVER\n");
TASS Belgium NV 131:4758606c9316 805 optlen = PICO_DHCP_OPTLEN_MSGTYPE + PICO_DHCP_OPTLEN_MAXMSGSIZE + PICO_DHCP_OPTLEN_PARAMLIST + PICO_DHCP_OPTLEN_END;
tass picotcp@tass.be 149:5f4cb161cec3 806 hdr = PICO_ZALLOC((size_t)(sizeof(struct pico_dhcp_hdr) + optlen));
tass picotcp@tass.be 149:5f4cb161cec3 807 if (!hdr) {
tass picotcp@tass.be 149:5f4cb161cec3 808 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 809 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 810 }
tass picotcp@tass.be 149:5f4cb161cec3 811
TASS Belgium NV 131:4758606c9316 812 /* specific options */
tass 154:6c0e92a80c4a 813 offset = (uint16_t)(offset + pico_dhcp_opt_maxmsgsize(DHCP_OPT(hdr,offset), DHCP_CLIENT_MAXMSGZISE));
TASS Belgium NV 131:4758606c9316 814 break;
tass 68:0847e35d08a6 815
tass 68:0847e35d08a6 816 case PICO_DHCP_MSG_REQUEST:
TASS Belgium NV 131:4758606c9316 817 optlen = PICO_DHCP_OPTLEN_MSGTYPE + PICO_DHCP_OPTLEN_MAXMSGSIZE + PICO_DHCP_OPTLEN_PARAMLIST + PICO_DHCP_OPTLEN_REQIP + PICO_DHCP_OPTLEN_SERVERID
TASS Belgium NV 131:4758606c9316 818 + PICO_DHCP_OPTLEN_END;
tass picotcp@tass.be 149:5f4cb161cec3 819 hdr = PICO_ZALLOC(sizeof(struct pico_dhcp_hdr) + optlen);
tass picotcp@tass.be 149:5f4cb161cec3 820 if (!hdr) {
tass picotcp@tass.be 149:5f4cb161cec3 821 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 822 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 823 }
tass picotcp@tass.be 149:5f4cb161cec3 824
TASS Belgium NV 131:4758606c9316 825 /* specific options */
tass 154:6c0e92a80c4a 826 offset = (uint16_t)(offset + pico_dhcp_opt_maxmsgsize(DHCP_OPT(hdr,offset), DHCP_CLIENT_MAXMSGZISE));
TASS Belgium NV 131:4758606c9316 827 if (dhcpc->state == DHCP_CLIENT_STATE_REQUESTING) {
tass 154:6c0e92a80c4a 828 offset = (uint16_t)(offset + pico_dhcp_opt_reqip(DHCP_OPT(hdr,offset), &dhcpc->address));
tass 154:6c0e92a80c4a 829 offset = (uint16_t)(offset + pico_dhcp_opt_serverid(DHCP_OPT(hdr,offset), &dhcpc->server_id));
TASS Belgium NV 131:4758606c9316 830 }
TASS Belgium NV 131:4758606c9316 831
TASS Belgium NV 131:4758606c9316 832 break;
tass 68:0847e35d08a6 833
tass 68:0847e35d08a6 834 default:
TASS Belgium NV 131:4758606c9316 835 return -1;
TASS Belgium NV 131:4758606c9316 836 }
tass 68:0847e35d08a6 837
TASS Belgium NV 131:4758606c9316 838 /* common options */
tass 154:6c0e92a80c4a 839 offset = (uint16_t)(offset + pico_dhcp_opt_msgtype(DHCP_OPT(hdr,offset), msg_type));
tass 154:6c0e92a80c4a 840 offset = (uint16_t)(offset + pico_dhcp_opt_paramlist(DHCP_OPT(hdr,offset)));
tass 154:6c0e92a80c4a 841 offset = (uint16_t)(offset + pico_dhcp_opt_end(DHCP_OPT(hdr,offset)));
tass 68:0847e35d08a6 842
TASS Belgium NV 131:4758606c9316 843 switch (dhcpc->state)
TASS Belgium NV 131:4758606c9316 844 {
tass 68:0847e35d08a6 845 case DHCP_CLIENT_STATE_BOUND:
TASS Belgium NV 131:4758606c9316 846 destination.addr = dhcpc->server_id.addr;
TASS Belgium NV 131:4758606c9316 847 hdr->ciaddr = dhcpc->address.addr;
TASS Belgium NV 131:4758606c9316 848 break;
tass 68:0847e35d08a6 849
tass 68:0847e35d08a6 850 case DHCP_CLIENT_STATE_RENEWING:
TASS Belgium NV 131:4758606c9316 851 destination.addr = dhcpc->server_id.addr;
TASS Belgium NV 131:4758606c9316 852 hdr->ciaddr = dhcpc->address.addr;
TASS Belgium NV 131:4758606c9316 853 break;
tass 68:0847e35d08a6 854
tass 68:0847e35d08a6 855 case DHCP_CLIENT_STATE_REBINDING:
TASS Belgium NV 131:4758606c9316 856 hdr->ciaddr = dhcpc->address.addr;
TASS Belgium NV 131:4758606c9316 857 break;
tass 68:0847e35d08a6 858
tass 68:0847e35d08a6 859 default:
TASS Belgium NV 131:4758606c9316 860 /* do nothing */
TASS Belgium NV 131:4758606c9316 861 break;
TASS Belgium NV 131:4758606c9316 862 }
tass 68:0847e35d08a6 863
TASS Belgium NV 131:4758606c9316 864 /* header information */
TASS Belgium NV 131:4758606c9316 865 hdr->op = PICO_DHCP_OP_REQUEST;
TASS Belgium NV 131:4758606c9316 866 hdr->htype = PICO_DHCP_HTYPE_ETH;
TASS Belgium NV 131:4758606c9316 867 hdr->hlen = PICO_SIZE_ETH;
TASS Belgium NV 131:4758606c9316 868 hdr->xid = dhcpc->xid;
tass picotcp@tass.be 149:5f4cb161cec3 869 /* hdr->flags = short_be(PICO_DHCP_FLAG_BROADCAST); / * Nope: see bug #96! * / */
TASS Belgium NV 131:4758606c9316 870 hdr->dhcp_magic = PICO_DHCPD_MAGIC_COOKIE;
TASS Belgium NV 131:4758606c9316 871 /* copy client hardware address */
TASS Belgium NV 131:4758606c9316 872 memcpy(hdr->hwaddr, &dhcpc->dev->eth->mac, PICO_SIZE_ETH);
tass 68:0847e35d08a6 873
tass 152:a3d286bf94e5 874 if (destination.addr == PICO_IP4_BCAST)
tass 152:a3d286bf94e5 875 pico_ipv4_route_set_bcast_link(pico_ipv4_link_get(&dhcpc->address));
tass 152:a3d286bf94e5 876
TASS Belgium NV 131:4758606c9316 877 r = pico_socket_sendto(dhcpc->s, hdr, (int)(sizeof(struct pico_dhcp_hdr) + optlen), &destination, PICO_DHCPD_PORT);
tass picotcp@tass.be 149:5f4cb161cec3 878 PICO_FREE(hdr);
TASS Belgium NV 131:4758606c9316 879 if (r < 0)
TASS Belgium NV 131:4758606c9316 880 return -1;
tass 68:0847e35d08a6 881
TASS Belgium NV 131:4758606c9316 882 return 0;
tass 68:0847e35d08a6 883 }
tass 68:0847e35d08a6 884
tass 68:0847e35d08a6 885 static void pico_dhcp_client_wakeup(uint16_t ev, struct pico_socket *s)
tass 68:0847e35d08a6 886 {
tass 152:a3d286bf94e5 887
tass 152:a3d286bf94e5 888 uint8_t *buf;
TASS Belgium NV 131:4758606c9316 889 int r = 0;
TASS Belgium NV 131:4758606c9316 890 struct pico_dhcp_hdr *hdr = NULL;
TASS Belgium NV 131:4758606c9316 891 struct pico_dhcp_client_cookie *dhcpc = NULL;
TASS Belgium NV 131:4758606c9316 892
tass 152:a3d286bf94e5 893 if ((ev & PICO_SOCK_EV_RD) == 0)
TASS Belgium NV 131:4758606c9316 894 return;
tass 68:0847e35d08a6 895
tass 152:a3d286bf94e5 896 buf = PICO_ZALLOC(DHCP_CLIENT_MAXMSGZISE);
tass 152:a3d286bf94e5 897 if (!buf) {
tass 152:a3d286bf94e5 898 return;
tass 152:a3d286bf94e5 899 }
tass 152:a3d286bf94e5 900
TASS Belgium NV 131:4758606c9316 901 r = pico_socket_recvfrom(s, buf, DHCP_CLIENT_MAXMSGZISE, NULL, NULL);
TASS Belgium NV 131:4758606c9316 902 if (r < 0)
tass 152:a3d286bf94e5 903 goto out_discard_buf;
tass 68:0847e35d08a6 904
TASS Belgium NV 131:4758606c9316 905 /* If the 'xid' of an arriving message does not match the 'xid'
TASS Belgium NV 131:4758606c9316 906 * of the most recent transmitted message, the message must be
TASS Belgium NV 131:4758606c9316 907 * silently discarded. */
TASS Belgium NV 131:4758606c9316 908 hdr = (struct pico_dhcp_hdr *)buf;
TASS Belgium NV 131:4758606c9316 909 dhcpc = pico_dhcp_client_find_cookie(hdr->xid);
TASS Belgium NV 131:4758606c9316 910 if (!dhcpc)
tass 152:a3d286bf94e5 911 goto out_discard_buf;
TASS Belgium NV 131:4758606c9316 912
TASS Belgium NV 131:4758606c9316 913 dhcpc->event = (uint8_t)pico_dhcp_client_opt_parse(buf, (uint16_t)r);
TASS Belgium NV 131:4758606c9316 914 pico_dhcp_state_machine(dhcpc->event, dhcpc, buf);
tass 152:a3d286bf94e5 915
tass 152:a3d286bf94e5 916 out_discard_buf:
tass 152:a3d286bf94e5 917 PICO_FREE(buf);
tass 68:0847e35d08a6 918 }
tass 68:0847e35d08a6 919
tass 68:0847e35d08a6 920 void *pico_dhcp_get_identifier(uint32_t xid)
tass 68:0847e35d08a6 921 {
TASS Belgium NV 131:4758606c9316 922 return (void *)pico_dhcp_client_find_cookie(xid);
tass 68:0847e35d08a6 923 }
tass 68:0847e35d08a6 924
TASS Belgium NV 131:4758606c9316 925 struct pico_ip4 pico_dhcp_get_address(void*dhcpc)
tass 68:0847e35d08a6 926 {
TASS Belgium NV 131:4758606c9316 927 return ((struct pico_dhcp_client_cookie*)dhcpc)->address;
tass 68:0847e35d08a6 928 }
tass 68:0847e35d08a6 929
TASS Belgium NV 131:4758606c9316 930 struct pico_ip4 pico_dhcp_get_gateway(void*dhcpc)
tass 68:0847e35d08a6 931 {
TASS Belgium NV 131:4758606c9316 932 return ((struct pico_dhcp_client_cookie*)dhcpc)->gateway;
tass 68:0847e35d08a6 933 }
tass 68:0847e35d08a6 934
tass 127:476fed453d4d 935 struct pico_ip4 pico_dhcp_get_netmask(void *dhcpc)
tass 127:476fed453d4d 936 {
TASS Belgium NV 131:4758606c9316 937 return ((struct pico_dhcp_client_cookie*)dhcpc)->netmask;
tass 127:476fed453d4d 938 }
tass 127:476fed453d4d 939
tass 152:a3d286bf94e5 940 struct pico_ip4 pico_dhcp_get_nameserver(void*dhcpc, int index)
tass 152:a3d286bf94e5 941 {
tass 152:a3d286bf94e5 942 struct pico_ip4 fault = {
tass 152:a3d286bf94e5 943 .addr = 0xFFFFFFFFU
tass 152:a3d286bf94e5 944 };
tass 152:a3d286bf94e5 945 if ((index != 0) && (index != 1))
tass 152:a3d286bf94e5 946 return fault;
tass 128:ae39e6e81531 947
tass 152:a3d286bf94e5 948 return ((struct pico_dhcp_client_cookie*)dhcpc)->nameserver[index];
tass 152:a3d286bf94e5 949 }
tass 152:a3d286bf94e5 950
tass 152:a3d286bf94e5 951 int pico_dhcp_client_abort(uint32_t xid)
tass 68:0847e35d08a6 952 {
tass 152:a3d286bf94e5 953 return pico_dhcp_client_del_cookie(xid);
tass 68:0847e35d08a6 954 }
tass 68:0847e35d08a6 955 #endif