Changes in uspace/srv/net/dhcp/dhcp.c [c6bf6be:947e2ef] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/dhcp/dhcp.c
rc6bf6be r947e2ef 35 35 */ 36 36 37 #include <adt/list.h>38 37 #include <bitops.h> 39 #include <fibril_synch.h>40 38 #include <inet/addr.h> 41 39 #include <inet/dnsr.h> 42 40 #include <inet/inetcfg.h> 43 #include <io/log.h>44 41 #include <loc.h> 45 42 #include <net/in.h> … … 49 46 #include <stdlib.h> 50 47 51 #include "dhcp.h"52 48 #include "dhcp_std.h" 53 #include "transport.h" 54 55 enum { 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 }; 49 50 #define NAME "dhcp" 63 51 64 52 #define MAX_MSG_SIZE 1024 53 54 static int transport_fd = -1; 55 static inet_link_info_t link_info; 65 56 static uint8_t msgbuf[MAX_MSG_SIZE]; 66 67 /** List of registered links (of dhcp_link_t) */68 static list_t dhcp_links;69 70 static void dhcpsrv_discover_timeout(void *);71 static void dhcpsrv_request_timeout(void *);72 73 typedef enum {74 ds_bound,75 ds_fail,76 ds_init,77 ds_init_reboot,78 ds_rebinding,79 ds_renewing,80 ds_requesting,81 ds_selecting82 } dhcp_state_t;83 57 84 58 typedef struct { … … 95 69 } dhcp_offer_t; 96 70 97 typedef struct {98 /** Link to dhcp_links list */99 link_t links;100 /** Link service ID */101 service_id_t link_id;102 /** Link info */103 inet_link_info_t link_info;104 /** Transport */105 dhcp_transport_t dt;106 /** Transport timeout */107 fibril_timer_t *timeout;108 /** Number of retries */109 int retries_left;110 /** Link state */111 dhcp_state_t state;112 /** Last received offer */113 dhcp_offer_t offer;114 } dhcp_link_t;115 116 static void dhcpsrv_recv(void *, void *, size_t);117 118 71 /** Decode subnet mask into subnet prefix length. */ 119 72 static int subnet_mask_decode(uint32_t mask, int *bits) … … 148 101 } 149 102 150 static int dhcp_send_discover(dhcp_link_t *dlink) 103 static int dhcp_send(void *msg, size_t size) 104 { 105 struct sockaddr_in addr; 106 int rc; 107 108 addr.sin_family = AF_INET; 109 addr.sin_port = htons(dhcp_server_port); 110 addr.sin_addr.s_addr = htonl(addr32_broadcast_all_hosts); 111 112 rc = sendto(transport_fd, msg, size, 0, 113 (struct sockaddr *)&addr, sizeof(addr)); 114 if (rc != EOK) { 115 printf("Sending failed\n"); 116 return rc; 117 } 118 119 return EOK; 120 } 121 122 static int dhcp_send_discover(void) 151 123 { 152 124 dhcp_hdr_t *hdr = (dhcp_hdr_t *)msgbuf; … … 160 132 hdr->flags = flag_broadcast; 161 133 162 addr48( dlink->link_info.mac_addr, hdr->chaddr);134 addr48(link_info.mac_addr, hdr->chaddr); 163 135 hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic); 164 136 … … 168 140 opt[3] = opt_end; 169 141 170 return dhcp_send(&dlink->dt, msgbuf, sizeof(dhcp_hdr_t) + 4); 171 } 172 173 static int dhcp_send_request(dhcp_link_t *dlink, dhcp_offer_t *offer) 142 return dhcp_send(msgbuf, sizeof(dhcp_hdr_t) + 4); 143 } 144 145 static int dhcp_recv_msg(void **rmsg, size_t *rsize) 146 { 147 struct sockaddr_in src_addr; 148 socklen_t src_addr_size; 149 size_t recv_size; 150 int rc; 151 152 src_addr_size = sizeof(src_addr); 153 rc = recvfrom(transport_fd, msgbuf, MAX_MSG_SIZE, 0, 154 (struct sockaddr *)&src_addr, &src_addr_size); 155 if (rc < 0) { 156 printf("recvfrom failed (%d)\n", rc); 157 return rc; 158 } 159 160 recv_size = (size_t)rc; 161 *rmsg = msgbuf; 162 *rsize = recv_size; 163 164 return EOK; 165 } 166 167 static int dhcp_send_request(dhcp_offer_t *offer) 174 168 { 175 169 dhcp_hdr_t *hdr = (dhcp_hdr_t *)msgbuf; … … 184 178 hdr->flags = flag_broadcast; 185 179 hdr->ciaddr = host2uint32_t_be(offer->oaddr.addr); 186 addr48( dlink->link_info.mac_addr, hdr->chaddr);180 addr48(link_info.mac_addr, hdr->chaddr); 187 181 hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic); 188 182 … … 209 203 opt[i++] = opt_end; 210 204 211 return dhcp_send( &dlink->dt,msgbuf, sizeof(dhcp_hdr_t) + i);212 } 213 214 static int dhcp_ parse_reply(void *msg, size_t size, dhcp_offer_t *offer)205 return dhcp_send(msgbuf, sizeof(dhcp_hdr_t) + i); 206 } 207 208 static int dhcp_recv_reply(void *msg, size_t size, dhcp_offer_t *offer) 215 209 { 216 210 dhcp_hdr_t *hdr = (dhcp_hdr_t *)msg; … … 228 222 size_t i; 229 223 230 log_msg(LOG_DEFAULT, LVL_DEBUG, "Receive reply");224 printf("Receive reply\n"); 231 225 memset(offer, 0, sizeof(*offer)); 232 226 … … 237 231 return rc; 238 232 239 log_msg(LOG_DEFAULT, LVL_DEBUG, "Your IP address: %s", saddr);233 printf("Your IP address: %s\n", saddr); 240 234 free(saddr); 241 235 … … 246 240 return rc; 247 241 248 log_msg(LOG_DEFAULT, LVL_DEBUG, "Next server IP address: %s", saddr);242 printf("Next server IP address: %s\n", saddr); 249 243 free(saddr); 250 244 … … 255 249 return rc; 256 250 257 log_msg(LOG_DEFAULT, LVL_DEBUG, "Relay agent IP address: %s", saddr);251 printf("Relay agent IP address: %s\n", saddr); 258 252 free(saddr); 259 253 … … 326 320 327 321 if (!have_server_id) { 328 log_msg(LOG_DEFAULT, LVL_ERROR, "Missing server ID option.");322 printf("Missing server ID option.\n"); 329 323 return rc; 330 324 } 331 325 332 326 if (!have_subnet_mask) { 333 log_msg(LOG_DEFAULT, LVL_ERROR, "Missing subnet mask option.");327 printf("Missing subnet mask option.\n"); 334 328 return rc; 335 329 } … … 339 333 return rc; 340 334 341 log_msg(LOG_DEFAULT, LVL_DEBUG, "Offered network address: %s", saddr);335 printf("Offered network address: %s\n", saddr); 342 336 free(saddr); 343 337 … … 347 341 return rc; 348 342 349 log_msg(LOG_DEFAULT, LVL_DEBUG, "Router address: %s", saddr);343 printf("Router address: %s\n", saddr); 350 344 free(saddr); 351 345 } … … 356 350 return rc; 357 351 358 log_msg(LOG_DEFAULT, LVL_DEBUG, "DNS server: %s", saddr);352 printf("DNS server: %s\n", saddr); 359 353 free(saddr); 360 354 } … … 373 367 &addr_id); 374 368 if (rc != EOK) { 375 log_msg(LOG_DEFAULT, LVL_ERROR, 376 "Error creating IP address %s (%d)", "dhcp4a", rc); 369 printf("Error creating IP address %s (%d)\n", "dhcp4a", rc); 377 370 return rc; 378 371 } … … 385 378 rc = inetcfg_sroute_create("dhcpdef", &defr, &offer->router, &sroute_id); 386 379 if (rc != EOK) { 387 log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating "388 "default route %s (%d).", "dhcpdef",rc);380 printf("Error creating default route %s (%d).\n", "dhcpdef", 381 rc); 389 382 return rc; 390 383 } … … 394 387 rc = dnsr_set_srvaddr(&offer->dns_server); 395 388 if (rc != EOK) { 396 log_msg(LOG_DEFAULT, LVL_ERROR, "Error setting "397 "nameserver address (%d))", rc);389 printf("%s: Error setting nameserver address (%d))\n", 390 NAME, rc); 398 391 return rc; 399 392 } … … 403 396 } 404 397 405 void dhcpsrv_links_init(void) 406 { 407 list_initialize(&dhcp_links); 408 } 409 410 static dhcp_link_t *dhcpsrv_link_find(service_id_t link_id) 411 { 412 list_foreach(dhcp_links, links, dhcp_link_t, dlink) { 413 if (dlink->link_id == link_id) 414 return dlink; 415 } 416 417 return NULL; 418 } 419 420 static void dhcp_link_set_failed(dhcp_link_t *dlink) 421 { 422 log_msg(LOG_DEFAULT, LVL_NOTE, "Giving up on link %s", 423 dlink->link_info.name); 424 dlink->state = ds_fail; 425 } 426 427 int dhcpsrv_link_add(service_id_t link_id) 428 { 429 dhcp_link_t *dlink; 430 int rc; 431 432 log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcpsrv_link_add(%zu)", link_id); 433 434 if (dhcpsrv_link_find(link_id) != NULL) { 435 log_msg(LOG_DEFAULT, LVL_NOTE, "Link %zu already added", 436 link_id); 437 return EEXIST; 438 } 439 440 dlink = calloc(1, sizeof(dhcp_link_t)); 441 if (dlink == NULL) 442 return ENOMEM; 443 444 dlink->link_id = link_id; 445 dlink->timeout = fibril_timer_create(); 446 if (dlink->timeout == NULL) { 447 rc = ENOMEM; 448 goto error; 449 } 450 451 /* Get link hardware address */ 452 rc = inetcfg_link_get(link_id, &dlink->link_info); 453 if (rc != EOK) { 454 log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting properties " 455 "for link %zu.", link_id); 456 rc = EIO; 457 goto error; 458 } 459 460 rc = dhcp_transport_init(&dlink->dt, link_id, dhcpsrv_recv, dlink); 461 if (rc != EOK) { 462 log_msg(LOG_DEFAULT, LVL_ERROR, "Error initializing DHCP " 463 "transport for link %s.", dlink->link_info.name); 464 rc = EIO; 465 goto error; 466 } 467 468 dlink->state = ds_selecting; 469 470 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER"); 471 rc = dhcp_send_discover(dlink); 472 if (rc != EOK) { 473 log_msg(LOG_DEFAULT, LVL_ERROR, "Error sending DHCPDISCOVER."); 474 dhcp_link_set_failed(dlink); 475 rc = EIO; 476 goto error; 477 } 478 479 dlink->retries_left = dhcp_discover_retries; 480 fibril_timer_set(dlink->timeout, dhcp_discover_timeout_val, 481 dhcpsrv_discover_timeout, dlink); 482 483 list_append(&dlink->links, &dhcp_links); 484 485 return EOK; 486 error: 487 if (dlink != NULL && dlink->timeout != NULL) 488 fibril_timer_destroy(dlink->timeout); 489 free(dlink); 490 return rc; 491 } 492 493 int dhcpsrv_link_remove(service_id_t link_id) 494 { 495 return ENOTSUP; 496 } 497 498 static void dhcpsrv_recv_offer(dhcp_link_t *dlink, dhcp_offer_t *offer) 499 { 500 int rc; 501 502 if (dlink->state != ds_selecting) { 503 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received offer in state " 504 " %d, ignoring.", (int)dlink->state); 505 return; 506 } 507 508 fibril_timer_clear(dlink->timeout); 509 dlink->offer = *offer; 510 dlink->state = ds_requesting; 511 512 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPREQUEST"); 513 rc = dhcp_send_request(dlink, offer); 514 if (rc != EOK) { 515 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request."); 516 return; 517 } 518 519 dlink->retries_left = dhcp_request_retries; 520 fibril_timer_set(dlink->timeout, dhcp_request_timeout_val, 521 dhcpsrv_request_timeout, dlink); 522 } 523 524 static void dhcpsrv_recv_ack(dhcp_link_t *dlink, dhcp_offer_t *offer) 525 { 526 int rc; 527 528 if (dlink->state != ds_requesting) { 529 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received ack in state " 530 " %d, ignoring.", (int)dlink->state); 531 return; 532 } 533 534 fibril_timer_clear(dlink->timeout); 535 dlink->offer = *offer; 536 dlink->state = ds_bound; 537 538 rc = dhcp_cfg_create(dlink->link_id, offer); 539 if (rc != EOK) { 540 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error creating configuration."); 541 return; 542 } 543 544 log_msg(LOG_DEFAULT, LVL_NOTE, "%s: Successfully configured.", 545 dlink->link_info.name); 546 } 547 548 static void dhcpsrv_recv(void *arg, void *msg, size_t size) 549 { 550 dhcp_link_t *dlink = (dhcp_link_t *)arg; 398 int main(int argc, char *argv[]) 399 { 400 int fd; 401 struct sockaddr_in laddr; 402 void *msg; 403 service_id_t iplink; 404 size_t msg_size; 551 405 dhcp_offer_t offer; 552 406 int rc; 553 407 554 log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: dhcpsrv_recv() %zu bytes", 555 dlink->link_info.name, size); 556 557 rc = dhcp_parse_reply(msg, size, &offer); 408 if (argc < 2) { 409 printf("syntax: %s <ip-link>\n", NAME); 410 return 1; 411 } 412 413 rc = inetcfg_init(); 558 414 if (rc != EOK) { 559 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error parsing reply"); 560 return; 561 } 562 563 switch (offer.msg_type) { 564 case msg_dhcpoffer: 565 dhcpsrv_recv_offer(dlink, &offer); 566 break; 567 case msg_dhcpack: 568 dhcpsrv_recv_ack(dlink, &offer); 569 break; 570 default: 571 log_msg(LOG_DEFAULT, LVL_DEBUG, "Received unexpected " 572 "message type. %d", (int)offer.msg_type); 573 break; 574 } 575 } 576 577 static void dhcpsrv_discover_timeout(void *arg) 578 { 579 dhcp_link_t *dlink = (dhcp_link_t *)arg; 580 int rc; 581 582 assert(dlink->state == ds_selecting); 583 log_msg(LOG_DEFAULT, LVL_NOTE, "%s: dcpsrv_discover_timeout", 584 dlink->link_info.name); 585 586 if (dlink->retries_left == 0) { 587 log_msg(LOG_DEFAULT, LVL_NOTE, "Retries exhausted"); 588 dhcp_link_set_failed(dlink); 589 return; 590 } 591 --dlink->retries_left; 592 593 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER"); 594 rc = dhcp_send_discover(dlink); 415 printf("Error contacting inet configuration service.\n"); 416 return 1; 417 } 418 419 rc = loc_service_get_id(argv[1], &iplink, 0); 595 420 if (rc != EOK) { 596 log_msg(LOG_DEFAULT, LVL_ERROR, "Error sending DHCPDISCOVER"); 597 dhcp_link_set_failed(dlink); 598 return; 599 } 600 601 fibril_timer_set(dlink->timeout, dhcp_discover_timeout_val, 602 dhcpsrv_discover_timeout, dlink); 603 } 604 605 static void dhcpsrv_request_timeout(void *arg) 606 { 607 dhcp_link_t *dlink = (dhcp_link_t *)arg; 608 int rc; 609 610 assert(dlink->state == ds_requesting); 611 log_msg(LOG_DEFAULT, LVL_NOTE, "%s: dcpsrv_request_timeout", 612 dlink->link_info.name); 613 614 if (dlink->retries_left == 0) { 615 log_msg(LOG_DEFAULT, LVL_NOTE, "Retries exhausted"); 616 dhcp_link_set_failed(dlink); 617 return; 618 } 619 --dlink->retries_left; 620 621 log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPREQUEST"); 622 rc = dhcp_send_request(dlink, &dlink->offer); 421 printf("Error resolving service '%s'.\n", argv[1]); 422 return 1; 423 } 424 425 /* Get link hardware address */ 426 rc = inetcfg_link_get(iplink, &link_info); 623 427 if (rc != EOK) { 624 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request."); 625 dhcp_link_set_failed(dlink); 626 return; 627 } 628 629 fibril_timer_set(dlink->timeout, dhcp_request_timeout_val, 630 dhcpsrv_request_timeout, dlink); 428 printf("Error getting properties for link '%s'.\n", argv[1]); 429 return 1; 430 } 431 432 laddr.sin_family = AF_INET; 433 laddr.sin_port = htons(dhcp_client_port); 434 laddr.sin_addr.s_addr = INADDR_ANY; 435 436 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 437 if (fd < 0) 438 return 1; 439 440 printf("Bind socket.\n"); 441 rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)); 442 if (rc != EOK) 443 return 1; 444 445 printf("Set socket options\n"); 446 rc = setsockopt(fd, SOL_SOCKET, SO_IPLINK, &iplink, sizeof(iplink)); 447 if (rc != EOK) 448 return 1; 449 450 transport_fd = fd; 451 452 printf("Send DHCPDISCOVER\n"); 453 rc = dhcp_send_discover(); 454 if (rc != EOK) 455 return 1; 456 457 rc = dhcp_recv_msg(&msg, &msg_size); 458 if (rc != EOK) 459 return 1; 460 461 printf("Received %zu bytes\n", msg_size); 462 463 rc = dhcp_recv_reply(msg, msg_size, &offer); 464 if (rc != EOK) 465 return 1; 466 467 rc = dhcp_send_request(&offer); 468 if (rc != EOK) 469 return 1; 470 471 rc = dhcp_recv_msg(&msg, &msg_size); 472 if (rc != EOK) 473 return 1; 474 475 printf("Received %zu bytes\n", msg_size); 476 477 rc = dhcp_recv_reply(msg, msg_size, &offer); 478 if (rc != EOK) 479 return 1; 480 481 rc = dhcp_cfg_create(iplink, &offer); 482 if (rc != EOK) 483 return 1; 484 485 closesocket(fd); 486 return 0; 631 487 } 632 488
Note:
See TracChangeset
for help on using the changeset viewer.