source: mainline/uspace/srv/net/dhcp/dhcp.c@ 91ece11b

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 91ece11b was 3e6bca8, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Represent Ethernet address as a number instead of an array

Carefully document the design since this breaks the principle of least
surprise. Also add unit tests.

  • Property mode set to 100644
File size: 15.3 KB
RevLine 
[695b6ff]1/*
[f05edcb]2 * Copyright (c) 2021 Jiri Svoboda
[695b6ff]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup dhcp
30 * @{
31 */
32/**
33 * @file
34 * @brief DHCP client
35 */
36
[66ec63a]37#include <adt/list.h>
[695b6ff]38#include <bitops.h>
[fab2746]39#include <byteorder.h>
[5a324d99]40#include <errno.h>
[c1694b6b]41#include <str_error.h>
[b417559]42#include <fibril_synch.h>
[695b6ff]43#include <inet/addr.h>
[b4edc96]44#include <inet/eth_addr.h>
[695b6ff]45#include <inet/dnsr.h>
46#include <inet/inetcfg.h>
[bd88bee]47#include <io/log.h>
[695b6ff]48#include <loc.h>
49#include <stdio.h>
50#include <stdlib.h>
[1d6dd2a]51#include <str.h>
[695b6ff]52
[bd88bee]53#include "dhcp.h"
[695b6ff]54#include "dhcp_std.h"
[66ec63a]55#include "transport.h"
[695b6ff]56
[1b0602a3]57enum {
58 /** In microseconds */
59 dhcp_discover_timeout_val = 5 * 1000 * 1000,
60 /** In microseconds */
61 dhcp_request_timeout_val = 1 * 1000 * 1000,
62 dhcp_discover_retries = 5,
63 dhcp_request_retries = 3
64};
[b417559]65
[695b6ff]66#define MAX_MSG_SIZE 1024
67static uint8_t msgbuf[MAX_MSG_SIZE];
68
[b417559]69/** List of registered links (of dhcp_link_t) */
[66ec63a]70static list_t dhcp_links;
71
[b417559]72static void dhcpsrv_discover_timeout(void *);
73static void dhcpsrv_request_timeout(void *);
74
75typedef enum {
76 ds_bound,
[1b0602a3]77 ds_fail,
[b417559]78 ds_init,
79 ds_init_reboot,
80 ds_rebinding,
81 ds_renewing,
82 ds_requesting,
83 ds_selecting
84} dhcp_state_t;
85
[695b6ff]86typedef struct {
87 /** Message type */
88 enum dhcp_msg_type msg_type;
89 /** Offered address */
90 inet_naddr_t oaddr;
91 /** Server address */
92 inet_addr_t srv_addr;
93 /** Router address */
94 inet_addr_t router;
95 /** DNS server */
96 inet_addr_t dns_server;
97} dhcp_offer_t;
98
[66ec63a]99typedef struct {
[b417559]100 /** Link to dhcp_links list */
[66ec63a]101 link_t links;
[b417559]102 /** Link service ID */
[66ec63a]103 service_id_t link_id;
[b417559]104 /** Link info */
[66ec63a]105 inet_link_info_t link_info;
[b417559]106 /** Transport */
[66ec63a]107 dhcp_transport_t dt;
[b417559]108 /** Transport timeout */
109 fibril_timer_t *timeout;
[1b0602a3]110 /** Number of retries */
111 int retries_left;
[b417559]112 /** Link state */
113 dhcp_state_t state;
114 /** Last received offer */
115 dhcp_offer_t offer;
[66ec63a]116} dhcp_link_t;
117
118static void dhcpsrv_recv(void *, void *, size_t);
119
[695b6ff]120/** Decode subnet mask into subnet prefix length. */
[b7fd2a0]121static errno_t subnet_mask_decode(uint32_t mask, int *bits)
[695b6ff]122{
123 int zbits;
124 uint32_t nmask;
125
126 if (mask == 0xffffffff) {
127 *bits = 32;
128 return EOK;
129 }
130
131 zbits = 1 + fnzb32(mask ^ 0xffffffff);
132 nmask = BIT_RRANGE(uint32_t, zbits);
133
134 if ((mask ^ nmask) != 0xffffffff) {
135 /* The mask is not in the form 1**n,0**m */
136 return EINVAL;
137 }
138
139 *bits = 32 - zbits;
140 return EOK;
141}
142
143static uint32_t dhcp_uint32_decode(uint8_t *data)
144{
145 return
146 ((uint32_t)data[0] << 24) |
147 ((uint32_t)data[1] << 16) |
148 ((uint32_t)data[2] << 8) |
149 ((uint32_t)data[3]);
150}
151
[b7fd2a0]152static errno_t dhcp_send_discover(dhcp_link_t *dlink)
[695b6ff]153{
154 dhcp_hdr_t *hdr = (dhcp_hdr_t *)msgbuf;
155 uint8_t *opt = msgbuf + sizeof(dhcp_hdr_t);
156
157 memset(msgbuf, 0, MAX_MSG_SIZE);
158 hdr->op = op_bootrequest;
159 hdr->htype = 1; /* AHRD_ETHERNET */
[b4edc96]160 hdr->hlen = ETH_ADDR_SIZE;
[695b6ff]161 hdr->xid = host2uint32_t_be(42);
162 hdr->flags = flag_broadcast;
163
[3e6bca8]164 eth_addr_encode(&dlink->link_info.mac_addr, hdr->chaddr);
[695b6ff]165 hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
166
167 opt[0] = opt_msg_type;
168 opt[1] = 1;
169 opt[2] = msg_dhcpdiscover;
170 opt[3] = opt_end;
171
[66ec63a]172 return dhcp_send(&dlink->dt, msgbuf, sizeof(dhcp_hdr_t) + 4);
[695b6ff]173}
174
[b7fd2a0]175static errno_t dhcp_send_request(dhcp_link_t *dlink, dhcp_offer_t *offer)
[695b6ff]176{
177 dhcp_hdr_t *hdr = (dhcp_hdr_t *)msgbuf;
178 uint8_t *opt = msgbuf + sizeof(dhcp_hdr_t);
179 size_t i;
180
181 memset(msgbuf, 0, MAX_MSG_SIZE);
182 hdr->op = op_bootrequest;
183 hdr->htype = 1; /* AHRD_ETHERNET */
184 hdr->hlen = 6;
185 hdr->xid = host2uint32_t_be(42);
186 hdr->flags = flag_broadcast;
187 hdr->ciaddr = host2uint32_t_be(offer->oaddr.addr);
[3e6bca8]188 eth_addr_encode(&dlink->link_info.mac_addr, hdr->chaddr);
[695b6ff]189 hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
190
191 i = 0;
192
193 opt[i++] = opt_msg_type;
194 opt[i++] = 1;
195 opt[i++] = msg_dhcprequest;
196
197 opt[i++] = opt_req_ip_addr;
198 opt[i++] = 4;
199 opt[i++] = offer->oaddr.addr >> 24;
200 opt[i++] = (offer->oaddr.addr >> 16) & 0xff;
201 opt[i++] = (offer->oaddr.addr >> 8) & 0xff;
202 opt[i++] = offer->oaddr.addr & 0xff;
203
204 opt[i++] = opt_server_id;
205 opt[i++] = 4;
206 opt[i++] = offer->srv_addr.addr >> 24;
207 opt[i++] = (offer->srv_addr.addr >> 16) & 0xff;
208 opt[i++] = (offer->srv_addr.addr >> 8) & 0xff;
209 opt[i++] = offer->srv_addr.addr & 0xff;
210
211 opt[i++] = opt_end;
212
[66ec63a]213 return dhcp_send(&dlink->dt, msgbuf, sizeof(dhcp_hdr_t) + i);
[695b6ff]214}
215
[b7fd2a0]216static errno_t dhcp_parse_reply(void *msg, size_t size, dhcp_offer_t *offer)
[695b6ff]217{
218 dhcp_hdr_t *hdr = (dhcp_hdr_t *)msg;
219 inet_addr_t yiaddr;
220 inet_addr_t siaddr;
221 inet_addr_t giaddr;
222 uint32_t subnet_mask;
223 bool have_subnet_mask = false;
224 bool have_server_id = false;
225 int subnet_bits;
226 char *saddr;
227 uint8_t opt_type, opt_len;
228 uint8_t *msgb;
[b7fd2a0]229 errno_t rc;
[695b6ff]230 size_t i;
231
[bd88bee]232 log_msg(LOG_DEFAULT, LVL_DEBUG, "Receive reply");
[695b6ff]233 memset(offer, 0, sizeof(*offer));
234
[f023251]235 inet_addr_set(uint32_t_be2host(hdr->yiaddr), &yiaddr);
[695b6ff]236 rc = inet_addr_format(&yiaddr, &saddr);
237 if (rc != EOK)
238 return rc;
239
[bd88bee]240 log_msg(LOG_DEFAULT, LVL_DEBUG, "Your IP address: %s", saddr);
[695b6ff]241 free(saddr);
242
[f023251]243 inet_addr_set(uint32_t_be2host(hdr->siaddr), &siaddr);
[695b6ff]244 rc = inet_addr_format(&siaddr, &saddr);
245 if (rc != EOK)
246 return rc;
247
[bd88bee]248 log_msg(LOG_DEFAULT, LVL_DEBUG, "Next server IP address: %s", saddr);
[695b6ff]249 free(saddr);
250
[f023251]251 inet_addr_set(uint32_t_be2host(hdr->giaddr), &giaddr);
[695b6ff]252 rc = inet_addr_format(&giaddr, &saddr);
253 if (rc != EOK)
254 return rc;
255
[bd88bee]256 log_msg(LOG_DEFAULT, LVL_DEBUG, "Relay agent IP address: %s", saddr);
[695b6ff]257 free(saddr);
258
[f023251]259 inet_naddr_set(yiaddr.addr, 0, &offer->oaddr);
[695b6ff]260
261 msgb = (uint8_t *)msg;
262
263 i = sizeof(dhcp_hdr_t);
264 while (i < size) {
265 opt_type = msgb[i++];
266
267 if (opt_type == opt_pad)
268 continue;
269 if (opt_type == opt_end)
270 break;
271
272 if (i >= size)
273 return EINVAL;
274
275 opt_len = msgb[i++];
276
277 if (i + opt_len > size)
278 return EINVAL;
279
280 switch (opt_type) {
281 case opt_subnet_mask:
282 if (opt_len != 4)
283 return EINVAL;
284 subnet_mask = dhcp_uint32_decode(&msgb[i]);
285 rc = subnet_mask_decode(subnet_mask, &subnet_bits);
286 if (rc != EOK)
287 return EINVAL;
288 offer->oaddr.prefix = subnet_bits;
289 have_subnet_mask = true;
290 break;
291 case opt_msg_type:
292 if (opt_len != 1)
293 return EINVAL;
294 offer->msg_type = msgb[i];
295 break;
296 case opt_server_id:
297 if (opt_len != 4)
298 return EINVAL;
[f023251]299 inet_addr_set(dhcp_uint32_decode(&msgb[i]),
300 &offer->srv_addr);
[695b6ff]301 have_server_id = true;
302 break;
303 case opt_router:
304 if (opt_len != 4)
305 return EINVAL;
[f023251]306 inet_addr_set(dhcp_uint32_decode(&msgb[i]),
307 &offer->router);
[695b6ff]308 break;
309 case opt_dns_server:
[23ce2d9]310 if (opt_len < 4 || opt_len % 4 != 0)
[695b6ff]311 return EINVAL;
[23ce2d9]312 /* XXX Handle multiple DNS servers properly */
[f023251]313 inet_addr_set(dhcp_uint32_decode(&msgb[i]),
314 &offer->dns_server);
[695b6ff]315 break;
316 case opt_end:
317 break;
318 default:
319 break;
320 }
321
322 /* Advance to the next option */
323 i = i + opt_len;
324 }
325
326 if (!have_server_id) {
[bd88bee]327 log_msg(LOG_DEFAULT, LVL_ERROR, "Missing server ID option.");
[695b6ff]328 return rc;
329 }
330
331 if (!have_subnet_mask) {
[bd88bee]332 log_msg(LOG_DEFAULT, LVL_ERROR, "Missing subnet mask option.");
[695b6ff]333 return rc;
334 }
335
336 rc = inet_naddr_format(&offer->oaddr, &saddr);
337 if (rc != EOK)
338 return rc;
339
[bd88bee]340 log_msg(LOG_DEFAULT, LVL_DEBUG, "Offered network address: %s", saddr);
[695b6ff]341 free(saddr);
342
343 if (offer->router.addr != 0) {
344 rc = inet_addr_format(&offer->router, &saddr);
345 if (rc != EOK)
346 return rc;
347
[bd88bee]348 log_msg(LOG_DEFAULT, LVL_DEBUG, "Router address: %s", saddr);
[695b6ff]349 free(saddr);
350 }
351
352 if (offer->dns_server.addr != 0) {
353 rc = inet_addr_format(&offer->dns_server, &saddr);
354 if (rc != EOK)
355 return rc;
356
[bd88bee]357 log_msg(LOG_DEFAULT, LVL_DEBUG, "DNS server: %s", saddr);
[695b6ff]358 free(saddr);
359 }
360
361 return EOK;
362}
363
[b7fd2a0]364static errno_t dhcp_cfg_create(service_id_t iplink, dhcp_offer_t *offer)
[695b6ff]365{
[b7fd2a0]366 errno_t rc;
[695b6ff]367 service_id_t addr_id;
368 service_id_t sroute_id;
369 inet_naddr_t defr;
370
371 rc = inetcfg_addr_create_static("dhcp4a", &offer->oaddr, iplink,
372 &addr_id);
373 if (rc != EOK) {
[bd88bee]374 log_msg(LOG_DEFAULT, LVL_ERROR,
[c1694b6b]375 "Error creating IP address %s: %s", "dhcp4a", str_error(rc));
[695b6ff]376 return rc;
377 }
378
379 if (offer->router.addr != 0) {
[f023251]380 inet_naddr_set(0, 0, &defr);
[695b6ff]381
382 rc = inetcfg_sroute_create("dhcpdef", &defr, &offer->router, &sroute_id);
383 if (rc != EOK) {
[bd88bee]384 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating "
[c1694b6b]385 "default route %s: %s.", "dhcpdef", str_error(rc));
[695b6ff]386 return rc;
387 }
388 }
389
390 if (offer->dns_server.addr != 0) {
391 rc = dnsr_set_srvaddr(&offer->dns_server);
392 if (rc != EOK) {
[66ec63a]393 log_msg(LOG_DEFAULT, LVL_ERROR, "Error setting "
[c1694b6b]394 "nameserver address: %s)", str_error(rc));
[695b6ff]395 return rc;
396 }
397 }
398
399 return EOK;
400}
401
[b417559]402void dhcpsrv_links_init(void)
403{
404 list_initialize(&dhcp_links);
405}
406
407static dhcp_link_t *dhcpsrv_link_find(service_id_t link_id)
408{
409 list_foreach(dhcp_links, links, dhcp_link_t, dlink) {
410 if (dlink->link_id == link_id)
411 return dlink;
412 }
413
414 return NULL;
415}
416
[ee20e8a]417static void dhcp_link_set_failed(dhcp_link_t *dlink)
418{
419 log_msg(LOG_DEFAULT, LVL_NOTE, "Giving up on link %s",
420 dlink->link_info.name);
421 dlink->state = ds_fail;
422}
423
[b7fd2a0]424static errno_t dhcp_discover_proc(dhcp_link_t *dlink)
[053fc2b]425{
426 dlink->state = ds_selecting;
427
[b7fd2a0]428 errno_t rc = dhcp_send_discover(dlink);
[053fc2b]429 if (rc != EOK)
430 return EIO;
431
432 dlink->retries_left = dhcp_discover_retries;
[a35b458]433
[8a64320e]434 if ((dlink->timeout->state == fts_not_set) ||
435 (dlink->timeout->state == fts_fired))
[053fc2b]436 fibril_timer_set(dlink->timeout, dhcp_discover_timeout_val,
[8a64320e]437 dhcpsrv_discover_timeout, dlink);
[a35b458]438
[053fc2b]439 return rc;
440}
441
[b7fd2a0]442errno_t dhcpsrv_link_add(service_id_t link_id)
[695b6ff]443{
[66ec63a]444 dhcp_link_t *dlink;
[b7fd2a0]445 errno_t rc;
[695b6ff]446
[bd88bee]447 log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcpsrv_link_add(%zu)", link_id);
[695b6ff]448
[b417559]449 if (dhcpsrv_link_find(link_id) != NULL) {
[c6bf6be]450 log_msg(LOG_DEFAULT, LVL_NOTE, "Link %zu already added",
[b417559]451 link_id);
452 return EEXIST;
453 }
454
[66ec63a]455 dlink = calloc(1, sizeof(dhcp_link_t));
456 if (dlink == NULL)
457 return ENOMEM;
458
459 dlink->link_id = link_id;
[78192cc7]460 dlink->timeout = fibril_timer_create(NULL);
[b417559]461 if (dlink->timeout == NULL) {
462 rc = ENOMEM;
463 goto error;
464 }
[66ec63a]465
[947e2ef]466 /* Get link hardware address */
[66ec63a]467 rc = inetcfg_link_get(link_id, &dlink->link_info);
[947e2ef]468 if (rc != EOK) {
[bd88bee]469 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting properties "
470 "for link %zu.", link_id);
[66ec63a]471 rc = EIO;
472 goto error;
[947e2ef]473 }
[695b6ff]474
[66ec63a]475 rc = dhcp_transport_init(&dlink->dt, link_id, dhcpsrv_recv, dlink);
476 if (rc != EOK) {
477 log_msg(LOG_DEFAULT, LVL_ERROR, "Error initializing DHCP "
478 "transport for link %s.", dlink->link_info.name);
479 rc = EIO;
480 goto error;
481 }
[695b6ff]482
[bd88bee]483 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER");
[053fc2b]484 rc = dhcp_discover_proc(dlink);
[66ec63a]485 if (rc != EOK) {
[ee20e8a]486 log_msg(LOG_DEFAULT, LVL_ERROR, "Error sending DHCPDISCOVER.");
487 dhcp_link_set_failed(dlink);
[66ec63a]488 rc = EIO;
489 goto error;
490 }
[695b6ff]491
[b417559]492 list_append(&dlink->links, &dhcp_links);
[695b6ff]493
[bd88bee]494 return EOK;
[66ec63a]495error:
[b417559]496 if (dlink != NULL && dlink->timeout != NULL)
497 fibril_timer_destroy(dlink->timeout);
[66ec63a]498 free(dlink);
499 return rc;
[bd88bee]500}
501
[b7fd2a0]502errno_t dhcpsrv_link_remove(service_id_t link_id)
[bd88bee]503{
504 return ENOTSUP;
[695b6ff]505}
506
[b7fd2a0]507errno_t dhcpsrv_discover(service_id_t link_id)
[053fc2b]508{
509 log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcpsrv_link_add(%zu)", link_id);
[a35b458]510
[053fc2b]511 dhcp_link_t *dlink = dhcpsrv_link_find(link_id);
[a35b458]512
[053fc2b]513 if (dlink == NULL) {
514 log_msg(LOG_DEFAULT, LVL_NOTE, "Link %zu doesn't exist",
515 link_id);
516 return EINVAL;
517 }
[a35b458]518
[053fc2b]519 return dhcp_discover_proc(dlink);
520}
521
[b417559]522static void dhcpsrv_recv_offer(dhcp_link_t *dlink, dhcp_offer_t *offer)
523{
[b7fd2a0]524 errno_t rc;
[b417559]525
526 if (dlink->state != ds_selecting) {
527 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received offer in state "
528 " %d, ignoring.", (int)dlink->state);
529 return;
530 }
531
532 fibril_timer_clear(dlink->timeout);
533 dlink->offer = *offer;
534 dlink->state = ds_requesting;
535
536 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPREQUEST");
537 rc = dhcp_send_request(dlink, offer);
538 if (rc != EOK) {
539 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request.");
540 return;
541 }
542
[1b0602a3]543 dlink->retries_left = dhcp_request_retries;
544 fibril_timer_set(dlink->timeout, dhcp_request_timeout_val,
[b417559]545 dhcpsrv_request_timeout, dlink);
546}
547
548static void dhcpsrv_recv_ack(dhcp_link_t *dlink, dhcp_offer_t *offer)
549{
[b7fd2a0]550 errno_t rc;
[b417559]551
552 if (dlink->state != ds_requesting) {
553 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received ack in state "
554 " %d, ignoring.", (int)dlink->state);
555 return;
556 }
557
558 fibril_timer_clear(dlink->timeout);
559 dlink->offer = *offer;
560 dlink->state = ds_bound;
561
562 rc = dhcp_cfg_create(dlink->link_id, offer);
563 if (rc != EOK) {
564 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error creating configuration.");
565 return;
566 }
[ee20e8a]567
568 log_msg(LOG_DEFAULT, LVL_NOTE, "%s: Successfully configured.",
569 dlink->link_info.name);
[b417559]570}
571
[66ec63a]572static void dhcpsrv_recv(void *arg, void *msg, size_t size)
573{
574 dhcp_link_t *dlink = (dhcp_link_t *)arg;
575 dhcp_offer_t offer;
[b7fd2a0]576 errno_t rc;
[66ec63a]577
[ee20e8a]578 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: dhcpsrv_recv() %zu bytes",
579 dlink->link_info.name, size);
[66ec63a]580
581 rc = dhcp_parse_reply(msg, size, &offer);
582 if (rc != EOK) {
583 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error parsing reply");
584 return;
585 }
586
[b417559]587 switch (offer.msg_type) {
588 case msg_dhcpoffer:
589 dhcpsrv_recv_offer(dlink, &offer);
590 break;
591 case msg_dhcpack:
592 dhcpsrv_recv_ack(dlink, &offer);
593 break;
594 default:
595 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received unexpected "
596 "message type. %d", (int)offer.msg_type);
597 break;
[66ec63a]598 }
[b417559]599}
[66ec63a]600
[b417559]601static void dhcpsrv_discover_timeout(void *arg)
602{
603 dhcp_link_t *dlink = (dhcp_link_t *)arg;
[b7fd2a0]604 errno_t rc;
[b417559]605
606 assert(dlink->state == ds_selecting);
[8d58fca]607 log_msg(LOG_DEFAULT, LVL_NOTE, "%s: dhcpsrv_discover_timeout",
[ee20e8a]608 dlink->link_info.name);
[b417559]609
[1b0602a3]610 if (dlink->retries_left == 0) {
611 log_msg(LOG_DEFAULT, LVL_NOTE, "Retries exhausted");
[ee20e8a]612 dhcp_link_set_failed(dlink);
[1b0602a3]613 return;
614 }
615 --dlink->retries_left;
616
[b417559]617 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER");
618 rc = dhcp_send_discover(dlink);
619 if (rc != EOK) {
620 log_msg(LOG_DEFAULT, LVL_ERROR, "Error sending DHCPDISCOVER");
[ee20e8a]621 dhcp_link_set_failed(dlink);
[b417559]622 return;
[66ec63a]623 }
[b417559]624
[1b0602a3]625 fibril_timer_set(dlink->timeout, dhcp_discover_timeout_val,
[b417559]626 dhcpsrv_discover_timeout, dlink);
627}
628
629static void dhcpsrv_request_timeout(void *arg)
630{
631 dhcp_link_t *dlink = (dhcp_link_t *)arg;
[b7fd2a0]632 errno_t rc;
[b417559]633
634 assert(dlink->state == ds_requesting);
[8d58fca]635 log_msg(LOG_DEFAULT, LVL_NOTE, "%s: dhcpsrv_request_timeout",
[ee20e8a]636 dlink->link_info.name);
[b417559]637
[1b0602a3]638 if (dlink->retries_left == 0) {
639 log_msg(LOG_DEFAULT, LVL_NOTE, "Retries exhausted");
[ee20e8a]640 dhcp_link_set_failed(dlink);
[1b0602a3]641 return;
642 }
643 --dlink->retries_left;
644
[b417559]645 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPREQUEST");
646 rc = dhcp_send_request(dlink, &dlink->offer);
647 if (rc != EOK) {
648 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request.");
[ee20e8a]649 dhcp_link_set_failed(dlink);
[b417559]650 return;
651 }
652
[1b0602a3]653 fibril_timer_set(dlink->timeout, dhcp_request_timeout_val,
[b417559]654 dhcpsrv_request_timeout, dlink);
[66ec63a]655}
[bd88bee]656
[695b6ff]657/** @}
658 */
Note: See TracBrowser for help on using the repository browser.