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

Last change on this file since eec201d was 8d58fca, checked in by Jakub Jermar <jakub@…>, 7 years ago

dhcp: Fix typo

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