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. Our grandparent 268 * will be waiting for us to finish this, so signal him when 269 * we're done. 270 */ 271 272 if (do_adopt) { 273 int result; 274 275 result = dhcp_adopt(); 276 277 if (grandparent != (pid_t)0) { 278 dhcpmsg(MSG_DEBUG, "adoption complete, signalling " 279 "parent (%i) to exit.", grandparent); 280 (void) kill(grandparent, SIGALRM); 281 } 282 283 if (result == 0) 284 return (EXIT_FAILURE); 285 } 286 287 /* 288 * enter the main event loop; this is where all the real work 289 * takes place (through registering events and scheduling timers). 290 * this function only returns when the agent is shutting down. 291 */ 292 293 switch (iu_handle_events(eh, tq)) { 294 295 case -1: 296 dhcpmsg(MSG_WARNING, "iu_handle_events exited abnormally"); 297 break; 298 299 case DHCP_REASON_INACTIVITY: 300 dhcpmsg(MSG_INFO, "no interfaces to manage, shutting down..."); 301 break; 302 303 case DHCP_REASON_TERMINATE: 304 dhcpmsg(MSG_INFO, "received SIGTERM, shutting down..."); 305 break; 306 307 case DHCP_REASON_SIGNAL: 308 dhcpmsg(MSG_WARNING, "received unexpected signal, shutting " 309 "down..."); 310 break; 311 } 312 313 (void) iu_eh_unregister_signal(eh, SIGTHAW, NULL); 314 315 iu_eh_destroy(eh); 316 iu_tq_destroy(tq); 317 318 return (EXIT_SUCCESS); 319 } 320 321 /* 322 * drain_script(): event loop callback during shutdown 323 * 324 * input: eh_t *: unused 325 * void *: unused 326 * output: boolean_t: B_TRUE if event loop should exit; B_FALSE otherwise 327 */ 328 329 /* ARGSUSED */ 330 boolean_t 331 drain_script(iu_eh_t *ehp, void *arg) 332 { 333 if (shutdown_started == B_FALSE) { 334 shutdown_started = B_TRUE; 335 if (do_adopt == B_FALSE) /* see 4291141 */ 336 nuke_ifslist(B_TRUE); 337 } 338 return (script_count == 0); 339 } 340 341 /* 342 * accept_event(): accepts a new connection on the ipc socket and registers 343 * to receive its messages with the event handler 344 * 345 * input: iu_eh_t *: unused 346 * int: the file descriptor in the iu_eh_t * the connection came in on 347 * (other arguments unused) 348 * output: void 349 */ 350 351 /* ARGSUSED */ 352 static void 353 accept_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg) 354 { 355 int client_fd; 356 int is_priv; 357 358 if (dhcp_ipc_accept(fd, &client_fd, &is_priv) != 0) { 359 dhcpmsg(MSG_ERR, "accept_event: accept on ipc socket"); 360 return; 361 } 362 363 if (iu_register_event(eh, client_fd, POLLIN, ipc_event, 364 (void *)is_priv) == -1) { 365 dhcpmsg(MSG_ERROR, "accept_event: cannot register ipc socket " 366 "for callback"); 367 } 368 } 369 370 /* 371 * ipc_event(): processes incoming ipc requests 372 * 373 * input: iu_eh_t *: unused 374 * int: the file descriptor in the iu_eh_t * the request came in on 375 * short: unused 376 * iu_event_id_t: unused 377 * void *: indicates whether the request is from a privileged client 378 * output: void 379 */ 380 381 /* ARGSUSED */ 382 static void 383 ipc_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg) 384 { 385 dhcp_ipc_request_t *request; 386 struct ifslist *ifsp, *primary_ifsp; 387 int error, is_priv = (int)arg; 388 PKT_LIST *plp[2]; 389 dhcp_ipc_type_t cmd; 390 391 (void) iu_unregister_event(eh, id, NULL); 392 393 if (dhcp_ipc_recv_request(fd, &request, DHCP_IPC_REQUEST_WAIT) != 0) { 394 dhcpmsg(MSG_ERROR, "ipc_event: dhcp_ipc_recv_request failed"); 395 (void) dhcp_ipc_close(fd); 396 return; 397 } 398 399 cmd = DHCP_IPC_CMD(request->message_type); 400 if (cmd >= DHCP_NIPC) { 401 send_error_reply(request, DHCP_IPC_E_CMD_UNKNOWN, &fd); 402 return; 403 } 404 405 /* return EPERM for any of the privileged actions */ 406 407 if (!is_priv) { 408 switch (cmd) { 409 410 case DHCP_STATUS: 411 case DHCP_PING: 412 case DHCP_GET_TAG: 413 break; 414 415 default: 416 dhcpmsg(MSG_WARNING, "ipc_event: privileged ipc " 417 "command (%i) attempted on %s", cmd, 418 request->ifname); 419 420 send_error_reply(request, DHCP_IPC_E_PERM, &fd); 421 return; 422 } 423 } 424 425 /* 426 * try to locate the ifs associated with this command. if the 427 * command is DHCP_START or DHCP_INFORM, then if there isn't 428 * an ifs already, make one (there may already be one from a 429 * previous failed attempt to START or INFORM). otherwise, 430 * verify the interface is still valid. 431 */ 432 433 ifsp = lookup_ifs(request->ifname); 434 435 switch (cmd) { 436 437 case DHCP_START: /* FALLTHRU */ 438 case DHCP_INFORM: 439 /* 440 * it's possible that the interface already exists, but 441 * has been abandoned. usually in those cases we should 442 * return DHCP_IPC_E_UNKIF, but that makes little sense 443 * in the case of "start" or "inform", so just ignore 444 * the abandoned interface and start over anew. 445 */ 446 447 if (ifsp != NULL && verify_ifs(ifsp) == 0) 448 ifsp = NULL; 449 450 /* 451 * as part of initializing the ifs, insert_ifs() 452 * creates a DLPI stream at ifsp->if_dlpi_fd. 453 */ 454 455 if (ifsp == NULL) { 456 ifsp = insert_ifs(request->ifname, B_FALSE, &error); 457 if (ifsp == NULL) { 458 send_error_reply(request, error, &fd); 459 return; 460 } 461 } 462 break; 463 464 default: 465 if (ifsp == NULL) { 466 if (request->ifname[0] == '\0') 467 error = DHCP_IPC_E_NOPRIMARY; 468 else 469 error = DHCP_IPC_E_UNKIF; 470 471 send_error_reply(request, error, &fd); 472 return; 473 } 474 break; 475 } 476 477 if (verify_ifs(ifsp) == 0) { 478 send_error_reply(request, DHCP_IPC_E_UNKIF, &fd); 479 return; 480 } 481 482 if (ifsp->if_dflags & DHCP_IF_BOOTP) { 483 switch (cmd) { 484 485 case DHCP_EXTEND: 486 case DHCP_RELEASE: 487 case DHCP_INFORM: 488 send_error_reply(request, DHCP_IPC_E_BOOTP, &fd); 489 return; 490 491 default: 492 break; 493 } 494 } 495 496 /* 497 * verify that the interface is in a state which will allow the 498 * command. we do this up front so that we can return an error 499 * *before* needlessly cancelling an in-progress transaction. 500 */ 501 502 if (!ipc_cmd_allowed[ifsp->if_state][cmd]) { 503 send_error_reply(request, DHCP_IPC_E_OUTSTATE, &fd); 504 return; 505 } 506 507 if ((request->message_type & DHCP_PRIMARY) && is_priv) { 508 if ((primary_ifsp = lookup_ifs("")) != NULL) 509 primary_ifsp->if_dflags &= ~DHCP_IF_PRIMARY; 510 ifsp->if_dflags |= DHCP_IF_PRIMARY; 511 } 512 513 /* 514 * current design dictates that there can be only one 515 * outstanding transaction per interface -- this simplifies 516 * the code considerably and also fits well with RFC2131. 517 * it is worth classifying the different DHCP commands into 518 * synchronous (those which we will handle now and be done 519 * with) and asynchronous (those which require transactions 520 * and will be completed at an indeterminate time in the 521 * future): 522 * 523 * DROP: removes the agent's management of an interface. 524 * asynchronous as the script program may be invoked. 525 * 526 * PING: checks to see if the agent controls an interface. 527 * synchronous, since no packets need to be sent 528 * to the DHCP server. 529 * 530 * STATUS: returns information about the an interface. 531 * synchronous, since no packets need to be sent 532 * to the DHCP server. 533 * 534 * RELEASE: releases the agent's management of an interface 535 * and brings the interface down. asynchronous as 536 * the script program may be invoked. 537 * 538 * EXTEND: renews a lease. asynchronous, since the agent 539 * needs to wait for an ACK, etc. 540 * 541 * START: starts DHCP on an interface. asynchronous since 542 * the agent needs to wait for OFFERs, ACKs, etc. 543 * 544 * INFORM: obtains configuration parameters for an externally 545 * configured interface. asynchronous, since the 546 * agent needs to wait for an ACK. 547 * 548 * notice that EXTEND, INFORM, START, DROP and RELEASE are 549 * asynchronous. notice also that asynchronous commands may 550 * occur from within the agent -- for instance, the agent 551 * will need to do implicit EXTENDs to extend the lease. in 552 * order to make the code simpler, the following rules apply 553 * for asynchronous commands: 554 * 555 * there can only be one asynchronous command at a time per 556 * interface. the current asynchronous command is managed by 557 * the async_* api: async_start(), async_finish(), 558 * async_timeout(), async_cancel(), and async_pending(). 559 * async_start() starts management of a new asynchronous 560 * command on an interface, which should only be done after 561 * async_pending() is called to check that there are no 562 * pending asynchronous commands on that interface. when the 563 * command is completed, async_finish() should be called. all 564 * asynchronous commands have an associated timer, which calls 565 * async_timeout() when it times out. if async_timeout() 566 * decides that the asynchronous command should be cancelled 567 * (see below), it calls async_cancel() to attempt 568 * cancellation. 569 * 570 * asynchronous commands started by a user command have an 571 * associated ipc_action which provides the agent with 572 * information for how to get in touch with the user command 573 * when the action completes. these ipc_action records also 574 * have an associated timeout which may be infinite. 575 * ipc_action_start() should be called when starting an 576 * asynchronous command requested by a user, which sets up the 577 * timer and keeps track of the ipc information (file 578 * descriptor, request type). when the asynchronous command 579 * completes, ipc_action_finish() should be called to return a 580 * command status code to the user and close the ipc 581 * connection). if the command does not complete before the 582 * timer fires, ipc_action_timeout() is called which closes 583 * the ipc connection and returns DHCP_IPC_E_TIMEOUT to the 584 * user. note that independent of ipc_action_timeout(), 585 * ipc_action_finish() should be called. 586 * 587 * on a case-by-case basis, here is what happens (per interface): 588 * 589 * o when an asynchronous command is requested, then 590 * async_pending() is called to see if there is already 591 * an asynchronous event. if so, the command does not 592 * proceed, and if there is an associated ipc_action, 593 * the user command is sent DHCP_IPC_E_PEND. 594 * 595 * o otherwise, the the transaction is started with 596 * async_start(). if the transaction is on behalf 597 * of a user, ipc_action_start() is called to keep 598 * track of the ipc information and set up the 599 * ipc_action timer. 600 * 601 * o if the command completes normally and before a 602 * timeout fires, then async_finish() is called. 603 * if there was an associated ipc_action, 604 * ipc_action_finish() is called to complete it. 605 * 606 * o if the command fails before a timeout fires, then 607 * async_finish() is called, and the interface is 608 * is returned to a known state based on the command. 609 * if there was an associated ipc_action, 610 * ipc_action_finish() is called to complete it. 611 * 612 * o if the ipc_action timer fires before command 613 * completion, then DHCP_IPC_E_TIMEOUT is returned to 614 * the user. however, the transaction continues to 615 * be carried out asynchronously. 616 * 617 * o if async_timeout() fires before command completion, 618 * then if the command was internal to the agent, it 619 * is cancelled. otherwise, if it was a user command, 620 * then if the user is still waiting for the command 621 * to complete, the command continues and async_timeout() 622 * is rescheduled. 623 */ 624 625 switch (cmd) { 626 627 case DHCP_DROP: /* FALLTHRU */ 628 case DHCP_RELEASE: /* FALLTHRU */ 629 case DHCP_EXTEND: /* FALLTHRU */ 630 case DHCP_INFORM: /* FALLTHRU */ 631 case DHCP_START: 632 /* 633 * if shutdown request has been received, send back an error. 634 */ 635 if (shutdown_started) { 636 send_error_reply(request, DHCP_IPC_E_OUTSTATE, &fd); 637 return; 638 } 639 640 if (async_pending(ifsp)) { 641 send_error_reply(request, DHCP_IPC_E_PEND, &fd); 642 return; 643 } 644 645 if (ipc_action_start(ifsp, request, fd) == 0) { 646 dhcpmsg(MSG_WARNING, "ipc_event: ipc_action_start " 647 "failed for %s", ifsp->if_name); 648 send_error_reply(request, DHCP_IPC_E_MEMORY, &fd); 649 return; 650 } 651 652 if (async_start(ifsp, cmd, B_TRUE) == 0) { 653 ipc_action_finish(ifsp, DHCP_IPC_E_MEMORY); 654 return; 655 } 656 break; 657 658 default: 659 break; 660 } 661 662 switch (cmd) { 663 664 case DHCP_DROP: 665 (void) script_start(ifsp, EVENT_DROP, dhcp_drop, NULL, NULL); 666 return; 667 668 case DHCP_EXTEND: 669 (void) dhcp_extending(ifsp); 670 break; 671 672 case DHCP_GET_TAG: { 673 dhcp_optnum_t optnum; 674 DHCP_OPT *opt = NULL; 675 boolean_t did_alloc = B_FALSE; 676 PKT_LIST *ack = ifsp->if_ack; 677 678 /* 679 * verify the request makes sense. 680 */ 681 682 if (request->data_type != DHCP_TYPE_OPTNUM || 683 request->data_length != sizeof (dhcp_optnum_t)) { 684 send_error_reply(request, DHCP_IPC_E_PROTO, &fd); 685 return; 686 } 687 688 (void) memcpy(&optnum, request->buffer, sizeof (dhcp_optnum_t)); 689 load_option: 690 switch (optnum.category) { 691 692 case DSYM_SITE: /* FALLTHRU */ 693 case DSYM_STANDARD: 694 if (optnum.code <= DHCP_LAST_OPT) 695 opt = ack->opts[optnum.code]; 696 break; 697 698 case DSYM_VENDOR: 699 /* 700 * the test against VS_OPTION_START is broken up into 701 * two tests to avoid compiler warnings under intel. 702 */ 703 704 if ((optnum.code > VS_OPTION_START || 705 optnum.code == VS_OPTION_START) && 706 optnum.code <= VS_OPTION_END) 707 opt = ack->vs[optnum.code]; 708 break; 709 710 case DSYM_FIELD: 711 if (optnum.code + optnum.size > sizeof (PKT)) 712 break; 713 714 /* + 2 to account for option code and length byte */ 715 opt = malloc(optnum.size + 2); 716 if (opt == NULL) { 717 send_error_reply(request, DHCP_IPC_E_MEMORY, 718 &fd); 719 return; 720 } 721 722 did_alloc = B_TRUE; 723 opt->len = optnum.size; 724 opt->code = optnum.code; 725 (void) memcpy(&opt->value, (caddr_t)ack->pkt + 726 opt->code, opt->len); 727 728 break; 729 730 default: 731 send_error_reply(request, DHCP_IPC_E_PROTO, &fd); 732 return; 733 } 734 735 /* 736 * return the option payload, if there was one. the "+ 2" 737 * accounts for the option code number and length byte. 738 */ 739 740 if (opt != NULL) { 741 send_data_reply(request, &fd, 0, DHCP_TYPE_OPTION, opt, 742 opt->len + 2); 743 744 if (did_alloc) 745 free(opt); 746 return; 747 } else if (ack != ifsp->if_orig_ack) { 748 /* 749 * There wasn't any definition for the option in the 750 * current ack, so now retry with the original ack if 751 * the original ack is not the current ack. 752 */ 753 ack = ifsp->if_orig_ack; 754 goto load_option; 755 } 756 757 /* 758 * note that an "okay" response is returned either in 759 * the case of an unknown option or a known option 760 * with no payload. this is okay (for now) since 761 * dhcpinfo checks whether an option is valid before 762 * ever performing ipc with the agent. 763 */ 764 765 send_ok_reply(request, &fd); 766 return; 767 } 768 769 case DHCP_INFORM: 770 dhcp_inform(ifsp); 771 /* next destination: dhcp_acknak() */ 772 return; 773 774 case DHCP_PING: 775 if (ifsp->if_dflags & DHCP_IF_FAILED) 776 send_error_reply(request, DHCP_IPC_E_FAILEDIF, &fd); 777 else 778 send_ok_reply(request, &fd); 779 return; 780 781 case DHCP_RELEASE: 782 (void) script_start(ifsp, EVENT_RELEASE, dhcp_release, 783 "Finished with lease.", NULL); 784 return; 785 786 case DHCP_START: 787 (void) canonize_ifs(ifsp); 788 789 /* 790 * if we have a valid hostconf lying around, then jump 791 * into INIT_REBOOT. if it fails, we'll end up going 792 * through the whole selecting() procedure again. 793 */ 794 795 error = read_hostconf(ifsp->if_name, plp, 2); 796 if (error != -1) { 797 ifsp->if_orig_ack = ifsp->if_ack = plp[0]; 798 if (error > 1) { 799 /* 800 * Return indicated we had more than one packet 801 * second one is the original ack. Older 802 * versions of the agent wrote only one ack 803 * to the file, we now keep both the first 804 * ack as well as the last one. 805 */ 806 ifsp->if_orig_ack = plp[1]; 807 } 808 dhcp_init_reboot(ifsp); 809 /* next destination: dhcp_acknak() */ 810 return; 811 } 812 813 /* 814 * if not debugging, wait for a few seconds before 815 * going into SELECTING. 816 */ 817 818 if (debug_level == 0) { 819 if (iu_schedule_timer_ms(tq, 820 lrand48() % DHCP_SELECT_WAIT, dhcp_start, ifsp) 821 != -1) { 822 hold_ifs(ifsp); 823 /* next destination: dhcp_start() */ 824 return; 825 } 826 } 827 828 dhcp_selecting(ifsp); 829 /* next destination: dhcp_requesting() */ 830 return; 831 832 case DHCP_STATUS: { 833 dhcp_status_t status; 834 835 status.if_began = monosec_to_time(ifsp->if_curstart_monosec); 836 837 if (ifsp->if_lease == DHCP_PERM) { 838 status.if_t1 = DHCP_PERM; 839 status.if_t2 = DHCP_PERM; 840 status.if_lease = DHCP_PERM; 841 } else { 842 status.if_t1 = status.if_began + ifsp->if_t1; 843 status.if_t2 = status.if_began + ifsp->if_t2; 844 status.if_lease = status.if_began + ifsp->if_lease; 845 } 846 847 status.version = DHCP_STATUS_VER; 848 status.if_state = ifsp->if_state; 849 status.if_dflags = ifsp->if_dflags; 850 status.if_sent = ifsp->if_sent; 851 status.if_recv = ifsp->if_received; 852 status.if_bad_offers = ifsp->if_bad_offers; 853 854 (void) strlcpy(status.if_name, ifsp->if_name, IFNAMSIZ); 855 856 send_data_reply(request, &fd, 0, DHCP_TYPE_STATUS, &status, 857 sizeof (dhcp_status_t)); 858 return; 859 } 860 861 default: 862 return; 863 } 864 } 865 866 /* 867 * check_rtm_addr(): determine if routing socket message matches interface 868 * address 869 * 870 * input: struct if_msghdr *: pointer to routing socket message 871 * struct in_addr: IP address 872 * output: boolean_t 873 */ 874 static boolean_t 875 check_rtm_addr(struct ifa_msghdr *ifam, int msglen, struct in_addr addr) 876 { 877 char *cp, *lim; 878 uint_t flag; 879 struct sockaddr *sa; 880 struct sockaddr_in *sinp; 881 882 if (!(ifam->ifam_addrs & RTA_IFA)) 883 return (B_FALSE); 884 885 cp = (char *)(ifam + 1); 886 lim = (char *)ifam + msglen; 887 for (flag = 1; flag < RTA_IFA; flag <<= 1) { 888 if (ifam->ifam_addrs & flag) { 889 /* LINTED: alignment */ 890 sa = (struct sockaddr *)cp; 891 if ((char *)(sa + 1) > lim) 892 return (B_FALSE); 893 switch (sa->sa_family) { 894 case AF_UNIX: 895 cp += sizeof (struct sockaddr_un); 896 break; 897 case AF_INET: 898 cp += sizeof (struct sockaddr_in); 899 break; 900 case AF_LINK: 901 cp += sizeof (struct sockaddr_dl); 902 break; 903 case AF_INET6: 904 cp += sizeof (struct sockaddr_in6); 905 break; 906 default: 907 cp += sizeof (struct sockaddr); 908 break; 909 } 910 } 911 } 912 /* LINTED: alignment */ 913 sinp = (struct sockaddr_in *)cp; 914 if ((char *)(sinp + 1) > lim) 915 return (B_FALSE); 916 return (sinp->sin_addr.s_addr == addr.s_addr); 917 } 918 919 /* 920 * rtsock_event(): fetches routing socket messages and updates internal 921 * interface state based on those messages. 922 * 923 * input: iu_eh_t *: unused 924 * int: the routing socket file descriptor 925 * (other arguments unused) 926 * output: void 927 */ 928 929 /* ARGSUSED */ 930 static void 931 rtsock_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg) 932 { 933 struct ifslist *ifs; 934 union { 935 struct ifa_msghdr ifam; 936 char buf[1024]; 937 } msg; 938 uint16_t ifindex; 939 struct lifreq lifr; 940 char *fail; 941 int msglen; 942 943 if ((msglen = read(fd, &msg, sizeof (msg))) <= 0) 944 return; 945 946 /* 947 * These are the messages that can identify a particular logical 948 * interface by local IP address. 949 */ 950 if (msg.ifam.ifam_type != RTM_DELADDR && 951 msg.ifam.ifam_type != RTM_NEWADDR) 952 return; 953 954 /* Note that ifam_index is just 16 bits */ 955 ifindex = msg.ifam.ifam_index; 956 957 for (ifs = lookup_ifs_by_uindex(ifindex, NULL); 958 ifs != NULL; 959 ifs = lookup_ifs_by_uindex(ifindex, ifs)) { 960 961 /* 962 * The if_sock_ip_fd is set to a non-negative integer by 963 * configure_bound(). If it's negative, then DHCP doesn't 964 * think we're bound. 965 * 966 * For pre-bound interfaces, we want to check to see if the 967 * IFF_UP bit has been reported. This means that DAD is 968 * complete. 969 */ 970 if (ifs->if_sock_ip_fd == -1 && ifs->if_state != PRE_BOUND) 971 continue; 972 973 /* 974 * Since we cannot trust the flags reported by the routing 975 * socket (they're just 32 bits -- and thus never include 976 * IFF_DUPLICATE), and we can't trust the ifindex (it's only 16 977 * bits and also doesn't reflect the alias in use), we get 978 * flags on all matching interfaces, and go by that. 979 */ 980 (void) strlcpy(lifr.lifr_name, ifs->if_name, 981 sizeof (lifr.lifr_name)); 982 if (ioctl(ifs->if_sock_fd, SIOCGLIFFLAGS, &lifr) == -1) { 983 fail = "unable to retrieve interface flags"; 984 } else if (!check_rtm_addr(&msg.ifam, msglen, ifs->if_addr)) { 985 /* 986 * If the message is not about this logical interface, 987 * then just ignore it. 988 */ 989 continue; 990 } else if (lifr.lifr_flags & IFF_DUPLICATE) { 991 fail = "interface has duplicate address"; 992 } else { 993 /* 994 * If we're now up and we were waiting for that, then 995 * kick off this interface. DAD is done. 996 */ 997 if ((lifr.lifr_flags & IFF_UP) && 998 ifs->if_state == PRE_BOUND) 999 dhcp_bound_complete(ifs); 1000 1001 continue; 1002 } 1003 1004 if (ifs->if_sock_ip_fd != -1) { 1005 (void) close(ifs->if_sock_ip_fd); 1006 ifs->if_sock_ip_fd = -1; 1007 } 1008 dhcpmsg(MSG_ERROR, fail); 1009 1010 /* 1011 * The binding has evidently failed, so it's as though it never 1012 * happened. We need to do switch back to PRE_BOUND state so 1013 * that send_pkt_internal() uses DLPI instead of sockets. Our 1014 * logical interface has already been torn down by the kernel, 1015 * and thus we can't send DHCPDECLINE by way of regular IP. 1016 */ 1017 ifs->if_state = PRE_BOUND; 1018 1019 if (ifs->if_ack->opts[CD_DHCP_TYPE] != NULL) 1020 send_decline(ifs, fail, &ifs->if_addr); 1021 1022 ifs->if_bad_offers++; 1023 dhcp_restart(ifs); 1024 } 1025 } 1026