source: mainline/uspace/srv/net/dhcp/dhcp.c@ e211ea04

Last change on this file since e211ea04 was 46577995, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

After this commit, HelenOS is free of code that mixes error codes with non-error
values on the assumption that error codes are negative.

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