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