1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <stdlib.h> 30 #include <errno.h> 31 #include <locale.h> 32 #include <string.h> 33 #include <unistd.h> 34 #include <signal.h> 35 #include <stdio.h> 36 #include <stdio_ext.h> 37 #include <dhcp_hostconf.h> 38 #include <dhcpagent_ipc.h> 39 #include <dhcpmsg.h> 40 #include <netinet/dhcp.h> 41 #include <net/route.h> 42 #include <sys/sockio.h> 43 44 #include "async.h" 45 #include "agent.h" 46 #include "script_handler.h" 47 #include "util.h" 48 #include "class_id.h" 49 #include "states.h" 50 #include "packet.h" 51 52 #ifndef TEXT_DOMAIN 53 #define TEXT_DOMAIN "SYS_TEST" 54 #endif 55 56 iu_timer_id_t inactivity_id; 57 int class_id_len = 0; 58 char *class_id; 59 iu_eh_t *eh; 60 iu_tq_t *tq; 61 pid_t grandparent; 62 int rtsock_fd; 63 64 static boolean_t shutdown_started = B_FALSE; 65 static boolean_t do_adopt = B_FALSE; 66 static unsigned int debug_level = 0; 67 static iu_eh_callback_t accept_event, ipc_event, rtsock_event; 68 69 /* 70 * The ipc_cmd_allowed[] table indicates which IPC commands are allowed in 71 * which states; a non-zero value indicates the command is permitted. 72 * 73 * START is permitted if the interface is fresh, or if we are in the process 74 * of trying to obtain a lease (as a convenience to save the administrator 75 * from having to do an explicit DROP). EXTEND, RELEASE, and GET_TAG require 76 * a lease to be obtained in order to make sense. INFORM is permitted if the 77 * interface is fresh or has an INFORM in progress or previously done on it -- 78 * otherwise a DROP or RELEASE is first required. PING and STATUS always make 79 * sense and thus are always permitted, as is DROP in order to permit the 80 * administrator to always bail out. 81 */ 82 static int ipc_cmd_allowed[DHCP_NSTATES][DHCP_NIPC] = { 83 /* D E P R S S I G */ 84 /* R X I E T T N E */ 85 /* O T N L A A F T */ 86 /* P E G E R T O _ */ 87 /* . N . A T U R T */ 88 /* . D . S . S M A */ 89 /* . . . E . . . G */ 90 /* INIT */ { 1, 0, 1, 0, 1, 1, 1, 0 }, 91 /* SELECTING */ { 1, 0, 1, 0, 1, 1, 0, 0 }, 92 /* REQUESTING */ { 1, 0, 1, 0, 1, 1, 0, 0 }, 93 /* PRE_BOUND */ { 1, 1, 1, 1, 0, 1, 0, 1 }, 94 /* BOUND */ { 1, 1, 1, 1, 0, 1, 0, 1 }, 95 /* RENEWING */ { 1, 1, 1, 1, 0, 1, 0, 1 }, 96 /* REBINDING */ { 1, 1, 1, 1, 0, 1, 0, 1 }, 97 /* INFORMATION */ { 1, 0, 1, 0, 0, 1, 1, 1 }, 98 /* INIT_REBOOT */ { 1, 0, 1, 0, 1, 1, 0, 0 }, 99 /* ADOPTING */ { 1, 0, 1, 0, 0, 1, 0, 0 }, 100 /* INFORM_SENT */ { 1, 0, 1, 0, 0, 1, 1, 0 } 101 }; 102 103 int 104 main(int argc, char **argv) 105 { 106 boolean_t is_daemon = B_TRUE; 107 boolean_t is_verbose = B_FALSE; 108 int ipc_fd; 109 int c; 110 struct rlimit rl; 111 112 /* 113 * -l is ignored for compatibility with old agent. 114 */ 115 116 while ((c = getopt(argc, argv, "vd:l:fa")) != EOF) { 117 118 switch (c) { 119 120 case 'a': 121 do_adopt = B_TRUE; 122 grandparent = getpid(); 123 break; 124 125 case 'd': 126 debug_level = strtoul(optarg, NULL, 0); 127 break; 128 129 case 'f': 130 is_daemon = B_FALSE; 131 break; 132 133 case 'v': 134 is_verbose = B_TRUE; 135 break; 136 137 case '?': 138 (void) fprintf(stderr, "usage: %s [-a] [-d n] [-f] [-v]" 139 "\n", argv[0]); 140 return (EXIT_FAILURE); 141 142 default: 143 break; 144 } 145 } 146 147 (void) setlocale(LC_ALL, ""); 148 (void) textdomain(TEXT_DOMAIN); 149 150 if (geteuid() != 0) { 151 dhcpmsg_init(argv[0], B_FALSE, is_verbose, debug_level); 152 dhcpmsg(MSG_ERROR, "must be super-user"); 153 dhcpmsg_fini(); 154 return (EXIT_FAILURE); 155 } 156 157 if (is_daemon && daemonize() == 0) { 158 dhcpmsg_init(argv[0], B_FALSE, is_verbose, debug_level); 159 dhcpmsg(MSG_ERR, "cannot become daemon, exiting"); 160 dhcpmsg_fini(); 161 return (EXIT_FAILURE); 162 } 163 164 dhcpmsg_init(argv[0], is_daemon, is_verbose, debug_level); 165 (void) atexit(dhcpmsg_fini); 166 167 tq = iu_tq_create(); 168 eh = iu_eh_create(); 169 170 if (eh == NULL || tq == NULL) { 171 errno = ENOMEM; 172 dhcpmsg(MSG_ERR, "cannot create timer queue or event handler"); 173 return (EXIT_FAILURE); 174 } 175 176 /* 177 * ignore most signals that could be reasonably generated. 178 */ 179 180 (void) signal(SIGTERM, graceful_shutdown); 181 (void) signal(SIGQUIT, graceful_shutdown); 182 (void) signal(SIGPIPE, SIG_IGN); 183 (void) signal(SIGUSR1, SIG_IGN); 184 (void) signal(SIGUSR2, SIG_IGN); 185 (void) signal(SIGINT, SIG_IGN); 186 (void) signal(SIGHUP, SIG_IGN); 187 (void) signal(SIGCHLD, SIG_IGN); 188 189 /* 190 * upon SIGTHAW we need to refresh any non-infinite leases. 191 */ 192 193 (void) iu_eh_register_signal(eh, SIGTHAW, refresh_ifslist, NULL); 194 195 class_id = get_class_id(); 196 if (class_id != NULL) 197 class_id_len = strlen(class_id); 198 else 199 dhcpmsg(MSG_WARNING, "get_class_id failed, continuing " 200 "with no vendor class id"); 201 202 /* 203 * the inactivity timer is enabled any time there are no 204 * interfaces under DHCP control. if DHCP_INACTIVITY_WAIT 205 * seconds transpire without an interface under DHCP control, 206 * the agent shuts down. 207 */ 208 209 inactivity_id = iu_schedule_timer(tq, DHCP_INACTIVITY_WAIT, 210 inactivity_shutdown, NULL); 211 212 /* 213 * max out the number available descriptors, just in case.. 214 */ 215 216 rl.rlim_cur = RLIM_INFINITY; 217 rl.rlim_max = RLIM_INFINITY; 218 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 219 dhcpmsg(MSG_ERR, "setrlimit failed"); 220 221 (void) enable_extended_FILE_stdio(-1, -1); 222 223 /* 224 * create the ipc channel that the agent will listen for 225 * requests on, and register it with the event handler so that 226 * `accept_event' will be called back. 227 */ 228 229 switch (dhcp_ipc_init(&ipc_fd)) { 230 231 case 0: 232 break; 233 234 case DHCP_IPC_E_BIND: 235 dhcpmsg(MSG_ERROR, "dhcp_ipc_init: cannot bind to port " 236 "%i (agent already running?)", IPPORT_DHCPAGENT); 237 return (EXIT_FAILURE); 238 239 default: 240 dhcpmsg(MSG_ERROR, "dhcp_ipc_init failed"); 241 return (EXIT_FAILURE); 242 } 243 244 if (iu_register_event(eh, ipc_fd, POLLIN, accept_event, 0) == -1) { 245 dhcpmsg(MSG_ERR, "cannot register ipc fd for messages"); 246 return (EXIT_FAILURE); 247 } 248 249 /* 250 * Create the global routing socket. This is used for monitoring 251 * interface transitions, so that we learn about the kernel's Duplicate 252 * Address Detection status, and for inserting and removing default 253 * routes as learned from DHCP servers. 254 */ 255 rtsock_fd = socket(PF_ROUTE, SOCK_RAW, AF_INET); 256 if (rtsock_fd == -1) { 257 dhcpmsg(MSG_ERR, "cannot open routing socket"); 258 return (EXIT_FAILURE); 259 } 260 if (iu_register_event(eh, rtsock_fd, POLLIN, rtsock_event, 0) == -1) { 261 dhcpmsg(MSG_ERR, "cannot register routing socket for messages"); 262 return (EXIT_FAILURE); 263 } 264 265 /* 266 * if the -a (adopt) option was specified, try to adopt the 267 * kernel-managed interface before we start. 268 */ 269 270 if (do_adopt && dhcp_adopt() == 0) 271 return (EXIT_FAILURE); 272 273 /* 274 * enter the main event loop; this is where all the real work 275 * takes place (through registering events and scheduling timers). 276 * this function only returns when the agent is shutting down. 277 */ 278 279 switch (iu_handle_events(eh, tq)) { 280 281 case -1: 282 dhcpmsg(MSG_WARNING, "iu_handle_events exited abnormally"); 283 break; 284 285 case DHCP_REASON_INACTIVITY: 286 dhcpmsg(MSG_INFO, "no interfaces to manage, shutting down..."); 287 break; 288 289 case DHCP_REASON_TERMINATE: 290 dhcpmsg(MSG_INFO, "received SIGTERM, shutting down..."); 291 break; 292 293 case DHCP_REASON_SIGNAL: 294 dhcpmsg(MSG_WARNING, "received unexpected signal, shutting " 295 "down..."); 296 break; 297 } 298 299 (void) iu_eh_unregister_signal(eh, SIGTHAW, NULL); 300 301 iu_eh_destroy(eh); 302 iu_tq_destroy(tq); 303 304 return (EXIT_SUCCESS); 305 } 306 307 /* 308 * drain_script(): event loop callback during shutdown 309 * 310 * input: eh_t *: unused 311 * void *: unused 312 * output: boolean_t: B_TRUE if event loop should exit; B_FALSE otherwise 313 */ 314 315 /* ARGSUSED */ 316 boolean_t 317 drain_script(iu_eh_t *ehp, void *arg) 318 { 319 if (shutdown_started == B_FALSE) { 320 shutdown_started = B_TRUE; 321 if (do_adopt == B_FALSE) /* see 4291141 */ 322 nuke_ifslist(B_TRUE); 323 } 324 return (script_count == 0); 325 } 326 327 /* 328 * accept_event(): accepts a new connection on the ipc socket and registers 329 * to receive its messages with the event handler 330 * 331 * input: iu_eh_t *: unused 332 * int: the file descriptor in the iu_eh_t * the connection came in on 333 * (other arguments unused) 334 * output: void 335 */ 336 337 /* ARGSUSED */ 338 static void 339 accept_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg) 340 { 341 int client_fd; 342 int is_priv; 343 344 if (dhcp_ipc_accept(fd, &client_fd, &is_priv) != 0) { 345 dhcpmsg(MSG_ERR, "accept_event: accept on ipc socket"); 346 return; 347 } 348 349 if (iu_register_event(eh, client_fd, POLLIN, ipc_event, 350 (void *)is_priv) == -1) { 351 dhcpmsg(MSG_ERROR, "accept_event: cannot register ipc socket " 352 "for callback"); 353 } 354 } 355 356 /* 357 * ipc_event(): processes incoming ipc requests 358 * 359 * input: iu_eh_t *: unused 360 * int: the file descriptor in the iu_eh_t * the request came in on 361 * short: unused 362 * iu_event_id_t: unused 363 * void *: indicates whether the request is from a privileged client 364 * output: void 365 */ 366 367 /* ARGSUSED */ 368 static void 369 ipc_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg) 370 { 371 dhcp_ipc_request_t *request; 372 struct ifslist *ifsp, *primary_ifsp; 373 int error, is_priv = (int)arg; 374 PKT_LIST *plp[2]; 375 dhcp_ipc_type_t cmd; 376 377 (void) iu_unregister_event(eh, id, NULL); 378 379 if (dhcp_ipc_recv_request(fd, &request, DHCP_IPC_REQUEST_WAIT) != 0) { 380 dhcpmsg(MSG_ERROR, "ipc_event: dhcp_ipc_recv_request failed"); 381 (void) dhcp_ipc_close(fd); 382 return; 383 } 384 385 cmd = DHCP_IPC_CMD(request->message_type); 386 if (cmd >= DHCP_NIPC) { 387 send_error_reply(request, DHCP_IPC_E_CMD_UNKNOWN, &fd); 388 return; 389 } 390 391 /* return EPERM for any of the privileged actions */ 392 393 if (!is_priv) { 394 switch (cmd) { 395 396 case DHCP_STATUS: 397 case DHCP_PING: 398 case DHCP_GET_TAG: 399 break; 400 401 default: 402 dhcpmsg(MSG_WARNING, "ipc_event: privileged ipc " 403 "command (%i) attempted on %s", cmd, 404 request->ifname); 405 406 send_error_reply(request, DHCP_IPC_E_PERM, &fd); 407 return; 408 } 409 } 410 411 /* 412 * try to locate the ifs associated with this command. if the 413 * command is DHCP_START or DHCP_INFORM, then if there isn't 414 * an ifs already, make one (there may already be one from a 415 * previous failed attempt to START or INFORM). otherwise, 416 * verify the interface is still valid. 417 */ 418 419 ifsp = lookup_ifs(request->ifname); 420 421 switch (cmd) { 422 423 case DHCP_START: /* FALLTHRU */ 424 case DHCP_INFORM: 425 /* 426 * it's possible that the interface already exists, but 427 * has been abandoned. usually in those cases we should 428 * return DHCP_IPC_E_UNKIF, but that makes little sense 429 * in the case of "start" or "inform", so just ignore 430 * the abandoned interface and start over anew. 431 */ 432 433 if (ifsp != NULL && verify_ifs(ifsp) == 0) 434 ifsp = NULL; 435 436 /* 437 * as part of initializing the ifs, insert_ifs() 438 * creates a DLPI stream at ifsp->if_dlpi_fd. 439 */ 440 441 if (ifsp == NULL) { 442 ifsp = insert_ifs(request->ifname, B_FALSE, &error); 443 if (ifsp == NULL) { 444 send_error_reply(request, error, &fd); 445 return; 446 } 447 } 448 break; 449 450 default: 451 if (ifsp == NULL) { 452 if (request->ifname[0] == '\0') 453 error = DHCP_IPC_E_NOPRIMARY; 454 else 455 error = DHCP_IPC_E_UNKIF; 456 457 send_error_reply(request, error, &fd); 458 return; 459 } 460 break; 461 } 462 463 if (verify_ifs(ifsp) == 0) { 464 send_error_reply(request, DHCP_IPC_E_UNKIF, &fd); 465 return; 466 } 467 468 if (ifsp->if_dflags & DHCP_IF_BOOTP) { 469 switch (cmd) { 470 471 case DHCP_EXTEND: 472 case DHCP_RELEASE: 473 case DHCP_INFORM: 474 send_error_reply(request, DHCP_IPC_E_BOOTP, &fd); 475 return; 476 477 default: 478 break; 479 } 480 } 481 482 /* 483 * verify that the interface is in a state which will allow the 484 * command. we do this up front so that we can return an error 485 * *before* needlessly cancelling an in-progress transaction. 486 */ 487 488 if (!ipc_cmd_allowed[ifsp->if_state][cmd]) { 489 send_error_reply(request, DHCP_IPC_E_OUTSTATE, &fd); 490 return; 491 } 492 493 if ((request->message_type & DHCP_PRIMARY) && is_priv) { 494 if ((primary_ifsp = lookup_ifs("")) != NULL) 495 primary_ifsp->if_dflags &= ~DHCP_IF_PRIMARY; 496 ifsp->if_dflags |= DHCP_IF_PRIMARY; 497 } 498 499 /* 500 * current design dictates that there can be only one 501 * outstanding transaction per interface -- this simplifies 502 * the code considerably and also fits well with RFC2131. 503 * it is worth classifying the different DHCP commands into 504 * synchronous (those which we will handle now and be done 505 * with) and asynchronous (those which require transactions 506 * and will be completed at an indeterminate time in the 507 * future): 508 * 509 * DROP: removes the agent's management of an interface. 510 * asynchronous as the script program may be invoked. 511 * 512 * PING: checks to see if the agent controls an interface. 513 * synchronous, since no packets need to be sent 514 * to the DHCP server. 515 * 516 * STATUS: returns information about the an interface. 517 * synchronous, since no packets need to be sent 518 * to the DHCP server. 519 * 520 * RELEASE: releases the agent's management of an interface 521 * and brings the interface down. asynchronous as 522 * the script program may be invoked. 523 * 524 * EXTEND: renews a lease. asynchronous, since the agent 525 * needs to wait for an ACK, etc. 526 * 527 * START: starts DHCP on an interface. asynchronous since 528 * the agent needs to wait for OFFERs, ACKs, etc. 529 * 530 * INFORM: obtains configuration parameters for an externally 531 * configured interface. asynchronous, since the 532 * agent needs to wait for an ACK. 533 * 534 * notice that EXTEND, INFORM, START, DROP and RELEASE are 535 * asynchronous. notice also that asynchronous commands may 536 * occur from within the agent -- for instance, the agent 537 * will need to do implicit EXTENDs to extend the lease. in 538 * order to make the code simpler, the following rules apply 539 * for asynchronous commands: 540 * 541 * there can only be one asynchronous command at a time per 542 * interface. the current asynchronous command is managed by 543 * the async_* api: async_start(), async_finish(), 544 * async_timeout(), async_cancel(), and async_pending(). 545 * async_start() starts management of a new asynchronous 546 * command on an interface, which should only be done after 547 * async_pending() is called to check that there are no 548 * pending asynchronous commands on that interface. when the 549 * command is completed, async_finish() should be called. all 550 * asynchronous commands have an associated timer, which calls 551 * async_timeout() when it times out. if async_timeout() 552 * decides that the asynchronous command should be cancelled 553 * (see below), it calls async_cancel() to attempt 554 * cancellation. 555 * 556 * asynchronous commands started by a user command have an 557 * associated ipc_action which provides the agent with 558 * information for how to get in touch with the user command 559 * when the action completes. these ipc_action records also 560 * have an associated timeout which may be infinite. 561 * ipc_action_start() should be called when starting an 562 * asynchronous command requested by a user, which sets up the 563 * timer and keeps track of the ipc information (file 564 * descriptor, request type). when the asynchronous command 565 * completes, ipc_action_finish() should be called to return a 566 * command status code to the user and close the ipc 567 * connection). if the command does not complete before the 568 * timer fires, ipc_action_timeout() is called which closes 569 * the ipc connection and returns DHCP_IPC_E_TIMEOUT to the 570 * user. note that independent of ipc_action_timeout(), 571 * ipc_action_finish() should be called. 572 * 573 * on a case-by-case basis, here is what happens (per interface): 574 * 575 * o when an asynchronous command is requested, then 576 * async_pending() is called to see if there is already 577 * an asynchronous event. if so, the command does not 578 * proceed, and if there is an associated ipc_action, 579 * the user command is sent DHCP_IPC_E_PEND. 580 * 581 * o otherwise, the the transaction is started with 582 * async_start(). if the transaction is on behalf 583 * of a user, ipc_action_start() is called to keep 584 * track of the ipc information and set up the 585 * ipc_action timer. 586 * 587 * o if the command completes normally and before a 588 * timeout fires, then async_finish() is called. 589 * if there was an associated ipc_action, 590 * ipc_action_finish() is called to complete it. 591 * 592 * o if the command fails before a timeout fires, then 593 * async_finish() is called, and the interface is 594 * is returned to a known state based on the command. 595 * if there was an associated ipc_action, 596 * ipc_action_finish() is called to complete it. 597 * 598 * o if the ipc_action timer fires before command 599 * completion, then DHCP_IPC_E_TIMEOUT is returned to 600 * the user. however, the transaction continues to 601 * be carried out asynchronously. 602 * 603 * o if async_timeout() fires before command completion, 604 * then if the command was internal to the agent, it 605 * is cancelled. otherwise, if it was a user command, 606 * then if the user is still waiting for the command 607 * to complete, the command continues and async_timeout() 608 * is rescheduled. 609 */ 610 611 switch (cmd) { 612 613 case DHCP_DROP: /* FALLTHRU */ 614 case DHCP_RELEASE: /* FALLTHRU */ 615 case DHCP_EXTEND: /* FALLTHRU */ 616 case DHCP_INFORM: /* FALLTHRU */ 617 case DHCP_START: 618 /* 619 * if shutdown request has been received, send back an error. 620 */ 621 if (shutdown_started) { 622 send_error_reply(request, DHCP_IPC_E_OUTSTATE, &fd); 623 return; 624 } 625 626 if (async_pending(ifsp)) { 627 send_error_reply(request, DHCP_IPC_E_PEND, &fd); 628 return; 629 } 630 631 if (ipc_action_start(ifsp, request, fd) == 0) { 632 dhcpmsg(MSG_WARNING, "ipc_event: ipc_action_start " 633 "failed for %s", ifsp->if_name); 634 send_error_reply(request, DHCP_IPC_E_MEMORY, &fd); 635 return; 636 } 637 638 if (async_start(ifsp, cmd, B_TRUE) == 0) { 639 ipc_action_finish(ifsp, DHCP_IPC_E_MEMORY); 640 return; 641 } 642 break; 643 644 default: 645 break; 646 } 647 648 switch (cmd) { 649 650 case DHCP_DROP: 651 (void) script_start(ifsp, EVENT_DROP, dhcp_drop, NULL, NULL); 652 return; 653 654 case DHCP_EXTEND: 655 (void) dhcp_extending(ifsp); 656 break; 657 658 case DHCP_GET_TAG: { 659 dhcp_optnum_t optnum; 660 DHCP_OPT *opt = NULL; 661 boolean_t did_alloc = B_FALSE; 662 PKT_LIST *ack = ifsp->if_ack; 663 664 /* 665 * verify the request makes sense. 666 */ 667 668 if (request->data_type != DHCP_TYPE_OPTNUM || 669 request->data_length != sizeof (dhcp_optnum_t)) { 670 send_error_reply(request, DHCP_IPC_E_PROTO, &fd); 671 return; 672 } 673 674 (void) memcpy(&optnum, request->buffer, sizeof (dhcp_optnum_t)); 675 load_option: 676 switch (optnum.category) { 677 678 case DSYM_SITE: /* FALLTHRU */ 679 case DSYM_STANDARD: 680 if (optnum.code <= DHCP_LAST_OPT) 681 opt = ack->opts[optnum.code]; 682 break; 683 684 case DSYM_VENDOR: 685 /* 686 * the test against VS_OPTION_START is broken up into 687 * two tests to avoid compiler warnings under intel. 688 */ 689 690 if ((optnum.code > VS_OPTION_START || 691 optnum.code == VS_OPTION_START) && 692 optnum.code <= VS_OPTION_END) 693 opt = ack->vs[optnum.code]; 694 break; 695 696 case DSYM_FIELD: 697 if (optnum.code + optnum.size > sizeof (PKT)) 698 break; 699 700 /* + 2 to account for option code and length byte */ 701 opt = malloc(optnum.size + 2); 702 if (opt == NULL) { 703 send_error_reply(request, DHCP_IPC_E_MEMORY, 704 &fd); 705 return; 706 } 707 708 did_alloc = B_TRUE; 709 opt->len = optnum.size; 710 opt->code = optnum.code; 711 (void) memcpy(&opt->value, (caddr_t)ack->pkt + 712 opt->code, opt->len); 713 714 break; 715 716 default: 717 send_error_reply(request, DHCP_IPC_E_PROTO, &fd); 718 return; 719 } 720 721 /* 722 * return the option payload, if there was one. the "+ 2" 723 * accounts for the option code number and length byte. 724 */ 725 726 if (opt != NULL) { 727 send_data_reply(request, &fd, 0, DHCP_TYPE_OPTION, opt, 728 opt->len + 2); 729 730 if (did_alloc) 731 free(opt); 732 return; 733 } else if (ack != ifsp->if_orig_ack) { 734 /* 735 * There wasn't any definition for the option in the 736 * current ack, so now retry with the original ack if 737 * the original ack is not the current ack. 738 */ 739 ack = ifsp->if_orig_ack; 740 goto load_option; 741 } 742 743 /* 744 * note that an "okay" response is returned either in 745 * the case of an unknown option or a known option 746 * with no payload. this is okay (for now) since 747 * dhcpinfo checks whether an option is valid before 748 * ever performing ipc with the agent. 749 */ 750 751 send_ok_reply(request, &fd); 752 return; 753 } 754 755 case DHCP_INFORM: 756 dhcp_inform(ifsp); 757 /* next destination: dhcp_acknak() */ 758 return; 759 760 case DHCP_PING: 761 if (ifsp->if_dflags & DHCP_IF_FAILED) 762 send_error_reply(request, DHCP_IPC_E_FAILEDIF, &fd); 763 else 764 send_ok_reply(request, &fd); 765 return; 766 767 case DHCP_RELEASE: 768 (void) script_start(ifsp, EVENT_RELEASE, dhcp_release, 769 "Finished with lease.", NULL); 770 return; 771 772 case DHCP_START: 773 (void) canonize_ifs(ifsp); 774 775 /* 776 * if we have a valid hostconf lying around, then jump 777 * into INIT_REBOOT. if it fails, we'll end up going 778 * through the whole selecting() procedure again. 779 */ 780 781 error = read_hostconf(ifsp->if_name, plp, 2); 782 if (error != -1) { 783 ifsp->if_orig_ack = ifsp->if_ack = plp[0]; 784 if (error > 1) { 785 /* 786 * Return indicated we had more than one packet 787 * second one is the original ack. Older 788 * versions of the agent wrote only one ack 789 * to the file, we now keep both the first 790 * ack as well as the last one. 791 */ 792 ifsp->if_orig_ack = plp[1]; 793 } 794 dhcp_init_reboot(ifsp); 795 /* next destination: dhcp_acknak() */ 796 return; 797 } 798 799 /* 800 * if not debugging, wait for a few seconds before 801 * going into SELECTING. 802 */ 803 804 if (debug_level == 0) { 805 if (iu_schedule_timer_ms(tq, 806 lrand48() % DHCP_SELECT_WAIT, dhcp_start, ifsp) 807 != -1) { 808 hold_ifs(ifsp); 809 /* next destination: dhcp_start() */ 810 return; 811 } 812 } 813 814 dhcp_selecting(ifsp); 815 /* next destination: dhcp_requesting() */ 816 return; 817 818 case DHCP_STATUS: { 819 dhcp_status_t status; 820 821 status.if_began = monosec_to_time(ifsp->if_curstart_monosec); 822 823 if (ifsp->if_lease == DHCP_PERM) { 824 status.if_t1 = DHCP_PERM; 825 status.if_t2 = DHCP_PERM; 826 status.if_lease = DHCP_PERM; 827 } else { 828 status.if_t1 = status.if_began + ifsp->if_t1; 829 status.if_t2 = status.if_began + ifsp->if_t2; 830 status.if_lease = status.if_began + ifsp->if_lease; 831 } 832 833 status.version = DHCP_STATUS_VER; 834 status.if_state = ifsp->if_state; 835 status.if_dflags = ifsp->if_dflags; 836 status.if_sent = ifsp->if_sent; 837 status.if_recv = ifsp->if_received; 838 status.if_bad_offers = ifsp->if_bad_offers; 839 840 (void) strlcpy(status.if_name, ifsp->if_name, IFNAMSIZ); 841 842 send_data_reply(request, &fd, 0, DHCP_TYPE_STATUS, &status, 843 sizeof (dhcp_status_t)); 844 return; 845 } 846 847 default: 848 return; 849 } 850 } 851 852 /* 853 * check_rtm_addr(): determine if routing socket message matches interface 854 * address 855 * 856 * input: struct if_msghdr *: pointer to routing socket message 857 * struct in_addr: IP address 858 * output: boolean_t 859 */ 860 static boolean_t 861 check_rtm_addr(struct ifa_msghdr *ifam, int msglen, struct in_addr addr) 862 { 863 char *cp, *lim; 864 uint_t flag; 865 struct sockaddr *sa; 866 struct sockaddr_in *sinp; 867 868 if (!(ifam->ifam_addrs & RTA_IFA)) 869 return (B_FALSE); 870 871 cp = (char *)(ifam + 1); 872 lim = (char *)ifam + msglen; 873 for (flag = 1; flag < RTA_IFA; flag <<= 1) { 874 if (ifam->ifam_addrs & flag) { 875 /* LINTED: alignment */ 876 sa = (struct sockaddr *)cp; 877 if ((char *)(sa + 1) > lim) 878 return (B_FALSE); 879 switch (sa->sa_family) { 880 case AF_UNIX: 881 cp += sizeof (struct sockaddr_un); 882 break; 883 case AF_INET: 884 cp += sizeof (struct sockaddr_in); 885 break; 886 case AF_LINK: 887 cp += sizeof (struct sockaddr_dl); 888 break; 889 case AF_INET6: 890 cp += sizeof (struct sockaddr_in6); 891 break; 892 default: 893 cp += sizeof (struct sockaddr); 894 break; 895 } 896 } 897 } 898 /* LINTED: alignment */ 899 sinp = (struct sockaddr_in *)cp; 900 if ((char *)(sinp + 1) > lim) 901 return (B_FALSE); 902 return (sinp->sin_addr.s_addr == addr.s_addr); 903 } 904 905 /* 906 * rtsock_event(): fetches routing socket messages and updates internal 907 * interface state based on those messages. 908 * 909 * input: iu_eh_t *: unused 910 * int: the routing socket file descriptor 911 * (other arguments unused) 912 * output: void 913 */ 914 915 /* ARGSUSED */ 916 static void 917 rtsock_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg) 918 { 919 struct ifslist *ifs; 920 union { 921 struct ifa_msghdr ifam; 922 char buf[1024]; 923 } msg; 924 uint16_t ifindex; 925 struct lifreq lifr; 926 char *fail; 927 int msglen; 928 DHCPSTATE oldstate; 929 930 if ((msglen = read(fd, &msg, sizeof (msg))) <= 0) 931 return; 932 933 /* 934 * These are the messages that can identify a particular logical 935 * interface by local IP address. 936 */ 937 if (msg.ifam.ifam_type != RTM_DELADDR && 938 msg.ifam.ifam_type != RTM_NEWADDR) 939 return; 940 941 /* Note that ifam_index is just 16 bits */ 942 ifindex = msg.ifam.ifam_index; 943 944 for (ifs = lookup_ifs_by_uindex(ifindex, NULL); 945 ifs != NULL; 946 ifs = lookup_ifs_by_uindex(ifindex, ifs)) { 947 948 /* 949 * The if_sock_ip_fd is set to a non-negative integer by 950 * configure_bound(). If it's negative, then DHCP doesn't 951 * think we're bound. 952 * 953 * For pre-bound interfaces, we want to check to see if the 954 * IFF_UP bit has been reported. This means that DAD is 955 * complete. 956 */ 957 oldstate = ifs->if_state; 958 if (ifs->if_sock_ip_fd == -1 && 959 (oldstate != PRE_BOUND && oldstate != ADOPTING)) 960 continue; 961 962 /* 963 * Since we cannot trust the flags reported by the routing 964 * socket (they're just 32 bits -- and thus never include 965 * IFF_DUPLICATE), and we can't trust the ifindex (it's only 16 966 * bits and also doesn't reflect the alias in use), we get 967 * flags on all matching interfaces, and go by that. 968 */ 969 (void) strlcpy(lifr.lifr_name, ifs->if_name, 970 sizeof (lifr.lifr_name)); 971 if (ioctl(ifs->if_sock_fd, SIOCGLIFFLAGS, &lifr) == -1) { 972 fail = "unable to retrieve interface flags on %s"; 973 lifr.lifr_flags = 0; 974 } else if (!check_rtm_addr(&msg.ifam, msglen, ifs->if_addr)) { 975 /* 976 * If the message is not about this logical interface, 977 * then just ignore it. 978 */ 979 continue; 980 } else if (lifr.lifr_flags & IFF_DUPLICATE) { 981 fail = "interface %s has duplicate address"; 982 } else { 983 /* 984 * If we're now up and we were waiting for that, then 985 * kick off this interface. DAD is done. 986 */ 987 if (lifr.lifr_flags & IFF_UP) { 988 if (oldstate == PRE_BOUND || 989 oldstate == ADOPTING) 990 dhcp_bound_complete(ifs); 991 if (oldstate == ADOPTING) 992 dhcp_adopt_complete(ifs); 993 } 994 continue; 995 } 996 997 if (ifs->if_sock_ip_fd != -1) { 998 (void) close(ifs->if_sock_ip_fd); 999 ifs->if_sock_ip_fd = -1; 1000 } 1001 dhcpmsg(MSG_ERROR, fail, ifs->if_name); 1002 1003 /* 1004 * The binding has evidently failed, so it's as though it never 1005 * happened. We need to do switch back to PRE_BOUND state so 1006 * that send_pkt_internal() uses DLPI instead of sockets. Our 1007 * logical interface has already been torn down by the kernel, 1008 * and thus we can't send DHCPDECLINE by way of regular IP. 1009 * (Unless we're adopting -- allow the grandparent to be 1010 * handled as expected.) 1011 */ 1012 if (oldstate != ADOPTING) 1013 ifs->if_state = PRE_BOUND; 1014 1015 if (ifs->if_ack->opts[CD_DHCP_TYPE] != NULL && 1016 (lifr.lifr_flags & IFF_DUPLICATE)) 1017 send_decline(ifs, fail, &ifs->if_addr); 1018 1019 ifs->if_bad_offers++; 1020 dhcp_restart(ifs); 1021 } 1022 } 1023