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.
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.
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]
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
34 #include <stdio_ext.h>
35 #include <dhcp_hostconf.h>
36 #include <dhcpagent_ipc.h>
37 #include <dhcpagent_util.h>
39 #include <netinet/dhcp.h>
40 #include <net/route.h>
41 #include <sys/sockio.h>
45 #include <sys/scsi/adapters/iscsi_if.h>
50 #include "script_handler.h"
55 #include "interface.h"
59 #define TEXT_DOMAIN "SYS_TEST"
62 iu_timer_id_t inactivity_id
;
70 static boolean_t shutdown_started
= B_FALSE
;
71 static boolean_t do_adopt
= B_FALSE
;
72 static unsigned int debug_level
= 0;
73 static iu_eh_callback_t accept_event
, ipc_event
, rtsock_event
;
76 * The ipc_cmd_allowed[] table indicates which IPC commands are allowed in
77 * which states; a non-zero value indicates the command is permitted.
79 * START is permitted if the state machine is fresh, or if we are in the
80 * process of trying to obtain a lease (as a convenience to save the
81 * administrator from having to do an explicit DROP). EXTEND, RELEASE, and
82 * GET_TAG require a lease to be obtained in order to make sense. INFORM is
83 * permitted if the interface is fresh or has an INFORM in progress or
84 * previously done on it -- otherwise a DROP or RELEASE is first required.
85 * PING and STATUS always make sense and thus are always permitted, as is DROP
86 * in order to permit the administrator to always bail out.
88 static int ipc_cmd_allowed
[DHCP_NSTATES
][DHCP_NIPC
] = {
96 /* INIT */ { 1, 0, 1, 0, 1, 1, 1, 0 },
97 /* SELECTING */ { 1, 0, 1, 0, 1, 1, 0, 0 },
98 /* REQUESTING */ { 1, 0, 1, 0, 1, 1, 0, 0 },
99 /* PRE_BOUND */ { 1, 1, 1, 1, 0, 1, 0, 1 },
100 /* BOUND */ { 1, 1, 1, 1, 0, 1, 0, 1 },
101 /* RENEWING */ { 1, 1, 1, 1, 0, 1, 0, 1 },
102 /* REBINDING */ { 1, 1, 1, 1, 0, 1, 0, 1 },
103 /* INFORMATION */ { 1, 0, 1, 0, 1, 1, 1, 1 },
104 /* INIT_REBOOT */ { 1, 0, 1, 1, 1, 1, 0, 0 },
105 /* ADOPTING */ { 1, 0, 1, 1, 0, 1, 0, 0 },
106 /* INFORM_SENT */ { 1, 0, 1, 0, 1, 1, 1, 0 },
107 /* DECLINING */ { 1, 1, 1, 1, 0, 1, 0, 1 },
108 /* RELEASING */ { 1, 0, 1, 0, 0, 1, 0, 1 },
111 #define CMD_ISPRIV 0x1 /* Command requires privileges */
112 #define CMD_CREATE 0x2 /* Command creates an interface */
113 #define CMD_BOOTP 0x4 /* Command is valid with BOOTP */
114 #define CMD_IMMED 0x8 /* Reply is immediate (no BUSY state) */
116 static uint_t ipc_cmd_flags
[DHCP_NIPC
] = {
117 /* DHCP_DROP */ CMD_ISPRIV
|CMD_BOOTP
,
118 /* DHCP_EXTEND */ CMD_ISPRIV
,
119 /* DHCP_PING */ CMD_BOOTP
|CMD_IMMED
,
120 /* DHCP_RELEASE */ CMD_ISPRIV
,
121 /* DHCP_START */ CMD_CREATE
|CMD_ISPRIV
|CMD_BOOTP
,
122 /* DHCP_STATUS */ CMD_BOOTP
|CMD_IMMED
,
123 /* DHCP_INFORM */ CMD_CREATE
|CMD_ISPRIV
,
124 /* DHCP_GET_TAG */ CMD_BOOTP
|CMD_IMMED
127 static boolean_t
is_iscsi_active(void);
130 main(int argc
, char **argv
)
132 boolean_t is_daemon
= B_TRUE
;
133 boolean_t is_verbose
;
136 int aware
= RTAW_UNDER_IPMP
;
139 debug_level
= df_get_int("", B_FALSE
, DF_DEBUG_LEVEL
);
140 is_verbose
= df_get_bool("", B_FALSE
, DF_VERBOSE
);
143 * -l is ignored for compatibility with old agent.
146 while ((c
= getopt(argc
, argv
, "vd:l:fa")) != EOF
) {
152 grandparent
= getpid();
156 debug_level
= strtoul(optarg
, NULL
, 0);
168 (void) fprintf(stderr
, "usage: %s [-a] [-d n] [-f] [-v]"
170 return (EXIT_FAILURE
);
177 (void) setlocale(LC_ALL
, "");
178 (void) textdomain(TEXT_DOMAIN
);
180 if (geteuid() != 0) {
181 dhcpmsg_init(argv
[0], B_FALSE
, is_verbose
, debug_level
);
182 dhcpmsg(MSG_ERROR
, "must be super-user");
184 return (EXIT_FAILURE
);
187 if (is_daemon
&& daemonize() == 0) {
188 dhcpmsg_init(argv
[0], B_FALSE
, is_verbose
, debug_level
);
189 dhcpmsg(MSG_ERR
, "cannot become daemon, exiting");
191 return (EXIT_FAILURE
);
195 * Seed the random number generator, since we're going to need it
196 * to set transaction id's and for exponential backoff.
198 srand48(gethrtime() ^ gethostid() ^ getpid());
200 dhcpmsg_init(argv
[0], is_daemon
, is_verbose
, debug_level
);
201 (void) atexit(dhcpmsg_fini
);
206 if (eh
== NULL
|| tq
== NULL
) {
208 dhcpmsg(MSG_ERR
, "cannot create timer queue or event handler");
209 return (EXIT_FAILURE
);
213 * ignore most signals that could be reasonably generated.
216 (void) signal(SIGTERM
, graceful_shutdown
);
217 (void) signal(SIGQUIT
, graceful_shutdown
);
218 (void) signal(SIGPIPE
, SIG_IGN
);
219 (void) signal(SIGUSR1
, SIG_IGN
);
220 (void) signal(SIGUSR2
, SIG_IGN
);
221 (void) signal(SIGINT
, SIG_IGN
);
222 (void) signal(SIGHUP
, SIG_IGN
);
223 (void) signal(SIGCHLD
, SIG_IGN
);
226 * upon SIGTHAW we need to refresh any non-infinite leases.
229 (void) iu_eh_register_signal(eh
, SIGTHAW
, refresh_smachs
, NULL
);
231 class_id
= get_class_id();
232 if (class_id
!= NULL
)
233 class_id_len
= strlen(class_id
);
235 dhcpmsg(MSG_WARNING
, "get_class_id failed, continuing "
236 "with no vendor class id");
239 * the inactivity timer is enabled any time there are no
240 * interfaces under DHCP control. if DHCP_INACTIVITY_WAIT
241 * seconds transpire without an interface under DHCP control,
242 * the agent shuts down.
245 inactivity_id
= iu_schedule_timer(tq
, DHCP_INACTIVITY_WAIT
,
246 inactivity_shutdown
, NULL
);
249 * max out the number available descriptors, just in case..
252 rl
.rlim_cur
= RLIM_INFINITY
;
253 rl
.rlim_max
= RLIM_INFINITY
;
254 if (setrlimit(RLIMIT_NOFILE
, &rl
) == -1)
255 dhcpmsg(MSG_ERR
, "setrlimit failed");
257 (void) enable_extended_FILE_stdio(-1, -1);
260 * Create and bind default IP sockets used to control interfaces and to
261 * catch stray packets.
264 if (!dhcp_ip_default())
265 return (EXIT_FAILURE
);
268 * create the ipc channel that the agent will listen for
269 * requests on, and register it with the event handler so that
270 * `accept_event' will be called back.
273 switch (dhcp_ipc_init(&ipc_fd
)) {
278 case DHCP_IPC_E_BIND
:
279 dhcpmsg(MSG_ERROR
, "dhcp_ipc_init: cannot bind to port "
280 "%i (agent already running?)", IPPORT_DHCPAGENT
);
281 return (EXIT_FAILURE
);
284 dhcpmsg(MSG_ERROR
, "dhcp_ipc_init failed");
285 return (EXIT_FAILURE
);
288 if (iu_register_event(eh
, ipc_fd
, POLLIN
, accept_event
, 0) == -1) {
289 dhcpmsg(MSG_ERR
, "cannot register ipc fd for messages");
290 return (EXIT_FAILURE
);
294 * Create the global routing socket. This is used for monitoring
295 * interface transitions, so that we learn about the kernel's Duplicate
296 * Address Detection status, and for inserting and removing default
297 * routes as learned from DHCP servers. Both v4 and v6 are handed
298 * with this one socket.
300 rtsock_fd
= socket(PF_ROUTE
, SOCK_RAW
, 0);
301 if (rtsock_fd
== -1) {
302 dhcpmsg(MSG_ERR
, "cannot open routing socket");
303 return (EXIT_FAILURE
);
307 * We're IPMP-aware and can manage IPMP test addresses, so issue
308 * RT_AWARE to get routing socket messages for interfaces under IPMP.
310 if (setsockopt(rtsock_fd
, SOL_ROUTE
, RT_AWARE
, &aware
,
311 sizeof (aware
)) == -1) {
312 dhcpmsg(MSG_ERR
, "cannot set RT_AWARE on routing socket");
313 return (EXIT_FAILURE
);
316 if (iu_register_event(eh
, rtsock_fd
, POLLIN
, rtsock_event
, 0) == -1) {
317 dhcpmsg(MSG_ERR
, "cannot register routing socket for messages");
318 return (EXIT_FAILURE
);
322 * if the -a (adopt) option was specified, try to adopt the
323 * kernel-managed interface before we start.
326 if (do_adopt
&& !dhcp_adopt())
327 return (EXIT_FAILURE
);
330 * For DHCPv6, we own all of the interfaces marked DHCPRUNNING. As
331 * we're starting operation here, if there are any of those interfaces
332 * lingering around, they're strays, and need to be removed.
334 * It might be nice to save these addresses off somewhere -- for both
335 * v4 and v6 -- and use them as hints for later negotiation.
340 * enter the main event loop; this is where all the real work
341 * takes place (through registering events and scheduling timers).
342 * this function only returns when the agent is shutting down.
345 switch (iu_handle_events(eh
, tq
)) {
348 dhcpmsg(MSG_WARNING
, "iu_handle_events exited abnormally");
351 case DHCP_REASON_INACTIVITY
:
352 dhcpmsg(MSG_INFO
, "no interfaces to manage, shutting down...");
355 case DHCP_REASON_TERMINATE
:
356 dhcpmsg(MSG_INFO
, "received SIGTERM, shutting down...");
359 case DHCP_REASON_SIGNAL
:
360 dhcpmsg(MSG_WARNING
, "received unexpected signal, shutting "
365 (void) iu_eh_unregister_signal(eh
, SIGTHAW
, NULL
);
370 return (EXIT_SUCCESS
);
374 * drain_script(): event loop callback during shutdown
376 * input: eh_t *: unused
378 * output: boolean_t: B_TRUE if event loop should exit; B_FALSE otherwise
383 drain_script(iu_eh_t
*ehp
, void *arg
)
385 if (shutdown_started
== B_FALSE
) {
386 shutdown_started
= B_TRUE
;
388 * Check if the system is diskless client and/or
389 * there are active iSCSI sessions
391 * Do not drop the lease, or the system will be
392 * unable to sync(dump) through nfs/iSCSI driver
394 if (!do_adopt
&& !is_iscsi_active()) {
398 return (script_count
== 0);
402 * accept_event(): accepts a new connection on the ipc socket and registers
403 * to receive its messages with the event handler
405 * input: iu_eh_t *: unused
406 * int: the file descriptor in the iu_eh_t * the connection came in on
407 * (other arguments unused)
413 accept_event(iu_eh_t
*ehp
, int fd
, short events
, iu_event_id_t id
, void *arg
)
418 if (dhcp_ipc_accept(fd
, &client_fd
, &is_priv
) != 0) {
419 dhcpmsg(MSG_ERR
, "accept_event: accept on ipc socket");
423 if (iu_register_event(eh
, client_fd
, POLLIN
, ipc_event
,
424 (void *)is_priv
) == -1) {
425 dhcpmsg(MSG_ERROR
, "accept_event: cannot register ipc socket "
431 * ipc_event(): processes incoming ipc requests
433 * input: iu_eh_t *: unused
434 * int: the file descriptor in the iu_eh_t * the request came in on
436 * iu_event_id_t: event ID
437 * void *: indicates whether the request is from a privileged client
443 ipc_event(iu_eh_t
*ehp
, int fd
, short events
, iu_event_id_t id
, void *arg
)
445 ipc_action_t ia
, *iap
;
447 int error
, is_priv
= (int)arg
;
450 boolean_t dsm_created
= B_FALSE
;
452 ipc_action_init(&ia
);
453 error
= dhcp_ipc_recv_request(fd
, &ia
.ia_request
,
454 DHCP_IPC_REQUEST_WAIT
);
455 if (error
!= DHCP_IPC_SUCCESS
) {
456 if (error
!= DHCP_IPC_E_EOF
) {
458 "ipc_event: dhcp_ipc_recv_request failed: %s",
459 dhcp_ipc_strerror(error
));
461 dhcpmsg(MSG_DEBUG
, "ipc_event: connection closed");
463 if ((dsmp
= lookup_smach_by_event(id
)) != NULL
) {
464 ipc_action_finish(dsmp
, error
);
466 (void) iu_unregister_event(eh
, id
, NULL
);
467 (void) dhcp_ipc_close(fd
);
472 /* Fill in temporary ipc_action structure for utility functions */
473 ia
.ia_cmd
= DHCP_IPC_CMD(ia
.ia_request
->message_type
);
477 if (ia
.ia_cmd
>= DHCP_NIPC
) {
479 "ipc_event: invalid command (%s) attempted on %s",
480 dhcp_ipc_type_to_string(ia
.ia_cmd
), ia
.ia_request
->ifname
);
481 send_error_reply(&ia
, DHCP_IPC_E_CMD_UNKNOWN
);
485 /* return EPERM for any of the privileged actions */
487 if (!is_priv
&& (ipc_cmd_flags
[ia
.ia_cmd
] & CMD_ISPRIV
)) {
489 "ipc_event: privileged ipc command (%s) attempted on %s",
490 dhcp_ipc_type_to_string(ia
.ia_cmd
), ia
.ia_request
->ifname
);
491 send_error_reply(&ia
, DHCP_IPC_E_PERM
);
496 * Try to locate the state machine associated with this command. If
497 * the command is DHCP_START or DHCP_INFORM and there isn't a state
498 * machine already, make one (there may already be one from a previous
499 * failed attempt to START or INFORM). Otherwise, verify the reference
502 * The interface name may be blank. In that case, we look up the
503 * primary interface, and the requested type (v4 or v6) doesn't matter.
506 isv6
= (ia
.ia_request
->message_type
& DHCP_V6
) != 0;
507 ifname
= ia
.ia_request
->ifname
;
509 dsmp
= primary_smach(isv6
);
511 dsmp
= lookup_smach(ifname
, isv6
);
514 /* Note that verify_smach drops a reference */
516 if (!verify_smach(dsmp
))
522 * If the user asked for the primary DHCP interface by giving
523 * an empty string and there is no primary, then check if we're
524 * handling dhcpinfo. If so, then simulate primary selection.
525 * Otherwise, report failure.
527 if (ifname
[0] == '\0') {
528 if (ia
.ia_cmd
== DHCP_GET_TAG
)
529 dsmp
= info_primary_smach(isv6
);
531 error
= DHCP_IPC_E_NOPRIMARY
;
534 * If there's no interface, and we're starting up, then create
535 * it now, along with a state machine for it. Note that if
536 * insert_smach fails, it discards the LIF reference.
538 } else if (ipc_cmd_flags
[ia
.ia_cmd
] & CMD_CREATE
) {
541 lif
= attach_lif(ifname
, isv6
, &error
);
543 (dsmp
= insert_smach(lif
, &error
)) != NULL
) {
545 * Get client ID for logical interface. (V4
546 * only, because V6 plumbs its own interfaces.)
548 error
= get_smach_cid(dsmp
);
549 if (error
!= DHCP_IPC_SUCCESS
) {
553 dsm_created
= (dsmp
!= NULL
);
557 * Otherwise, this is an operation on an unknown interface.
560 error
= DHCP_IPC_E_UNKIF
;
563 send_error_reply(&ia
, error
);
569 * If this is a request for DHCP to manage a lease on an address,
570 * ensure that IFF_DHCPRUNNING is set (we don't set this when the lif
571 * is created because the lif may have been created for INFORM).
573 if (ia
.ia_cmd
== DHCP_START
&&
574 (error
= set_lif_dhcp(dsmp
->dsm_lif
)) != DHCP_IPC_SUCCESS
) {
577 send_error_reply(&ia
, error
);
581 if ((dsmp
->dsm_dflags
& DHCP_IF_BOOTP
) &&
582 !(ipc_cmd_flags
[ia
.ia_cmd
] & CMD_BOOTP
)) {
583 dhcpmsg(MSG_ERROR
, "command %s not valid for BOOTP on %s",
584 dhcp_ipc_type_to_string(ia
.ia_cmd
), dsmp
->dsm_name
);
585 send_error_reply(&ia
, DHCP_IPC_E_BOOTP
);
590 * verify that the state machine is in a state which will allow the
591 * command. we do this up front so that we can return an error
592 * *before* needlessly cancelling an in-progress transaction.
595 if (!check_cmd_allowed(dsmp
->dsm_state
, ia
.ia_cmd
)) {
597 "in state %s; not allowing %s command on %s",
598 dhcp_state_to_string(dsmp
->dsm_state
),
599 dhcp_ipc_type_to_string(ia
.ia_cmd
), dsmp
->dsm_name
);
600 send_error_reply(&ia
,
601 ia
.ia_cmd
== DHCP_START
&& dsmp
->dsm_state
!= INIT
?
602 DHCP_IPC_E_RUNNING
: DHCP_IPC_E_OUTSTATE
);
606 dhcpmsg(MSG_DEBUG
, "in state %s; allowing %s command on %s",
607 dhcp_state_to_string(dsmp
->dsm_state
),
608 dhcp_ipc_type_to_string(ia
.ia_cmd
), dsmp
->dsm_name
);
610 if ((ia
.ia_request
->message_type
& DHCP_PRIMARY
) && is_priv
)
614 * The current design dictates that there can be only one outstanding
615 * transaction per state machine -- this simplifies the code
616 * considerably and also fits well with RFCs 2131 and 3315. It is
617 * worth classifying the different DHCP commands into synchronous
618 * (those which we will handle now and reply to immediately) and
619 * asynchronous (those which require transactions and will be completed
620 * at an indeterminate time in the future):
622 * DROP: removes the agent's management of a state machine.
623 * asynchronous as the script program may be invoked.
625 * PING: checks to see if the agent has a named state machine.
626 * synchronous, since no packets need to be sent
627 * to the DHCP server.
629 * STATUS: returns information about a state machine.
630 * synchronous, since no packets need to be sent
631 * to the DHCP server.
633 * RELEASE: releases the agent's management of a state machine
634 * and brings the associated interfaces down. asynchronous
635 * as the script program may be invoked.
637 * EXTEND: renews a lease. asynchronous, since the agent
638 * needs to wait for an ACK, etc.
640 * START: starts DHCP on a named state machine. asynchronous since
641 * the agent needs to wait for OFFERs, ACKs, etc.
643 * INFORM: obtains configuration parameters for the system using
644 * externally configured interface. asynchronous, since the
645 * agent needs to wait for an ACK.
647 * Notice that EXTEND, INFORM, START, DROP and RELEASE are
648 * asynchronous. Notice also that asynchronous commands may occur from
649 * within the agent -- for instance, the agent will need to do implicit
650 * EXTENDs to extend the lease. In order to make the code simpler, the
651 * following rules apply for asynchronous commands:
653 * There can only be one asynchronous command at a time per state
654 * machine. The current asynchronous command is managed by the async_*
655 * api: async_start(), async_finish(), and async_cancel().
656 * async_start() starts management of a new asynchronous command on an
657 * state machine, which should only be done after async_cancel() to
658 * terminate a previous command. When the command is completed,
659 * async_finish() should be called.
661 * Asynchronous commands started by a user command have an associated
662 * ipc_action which provides the agent with information for how to get
663 * in touch with the user command when the action completes. These
664 * ipc_action records also have an associated timeout which may be
665 * infinite. ipc_action_start() should be called when starting an
666 * asynchronous command requested by a user, which sets up the timer
667 * and keeps track of the ipc information (file descriptor, request
668 * type). When the asynchronous command completes, ipc_action_finish()
669 * should be called to return a command status code to the user and
670 * close the ipc connection). If the command does not complete before
671 * the timer fires, ipc_action_timeout() is called which closes the ipc
672 * connection and returns DHCP_IPC_E_TIMEOUT to the user. Note that
673 * independent of ipc_action_timeout(), ipc_action_finish() should be
676 * on a case-by-case basis, here is what happens (per state machine):
678 * o When an asynchronous command is requested, then
679 * async_cancel() is called to terminate any non-user
680 * action in progress. If there's a user action running,
681 * the user command is sent DHCP_IPC_E_PEND.
683 * o otherwise, the the transaction is started with
684 * async_start(). if the transaction is on behalf
685 * of a user, ipc_action_start() is called to keep
686 * track of the ipc information and set up the
689 * o if the command completes normally and before a
690 * timeout fires, then async_finish() is called.
691 * if there was an associated ipc_action,
692 * ipc_action_finish() is called to complete it.
694 * o if the command fails before a timeout fires, then
695 * async_finish() is called, and the state machine is
696 * is returned to a known state based on the command.
697 * if there was an associated ipc_action,
698 * ipc_action_finish() is called to complete it.
700 * o if the ipc_action timer fires before command
701 * completion, then DHCP_IPC_E_TIMEOUT is returned to
702 * the user. however, the transaction continues to
703 * be carried out asynchronously.
706 if (ipc_cmd_flags
[ia
.ia_cmd
] & CMD_IMMED
) {
708 * Only immediate commands (ping, status, get_tag) need to
709 * worry about freeing ia through one of the reply functions
715 * if shutdown request has been received, send back an error.
717 if (shutdown_started
) {
718 send_error_reply(&ia
, DHCP_IPC_E_OUTSTATE
);
722 if (dsmp
->dsm_dflags
& DHCP_IF_BUSY
) {
723 send_error_reply(&ia
, DHCP_IPC_E_PEND
);
727 if (!ipc_action_start(dsmp
, &ia
)) {
728 dhcpmsg(MSG_WARNING
, "ipc_event: ipc_action_start "
729 "failed for %s", dsmp
->dsm_name
);
730 send_error_reply(&ia
, DHCP_IPC_E_MEMORY
);
734 /* Action structure consumed by above function */
738 switch (iap
->ia_cmd
) {
741 if (dsmp
->dsm_droprelease
)
743 dsmp
->dsm_droprelease
= B_TRUE
;
746 * Ensure that a timer associated with the existing state
747 * doesn't pop while we're waiting for the script to complete.
748 * (If so, chaos can result -- e.g., a timer causes us to end
749 * up in dhcp_selecting() would start acquiring a new lease on
750 * dsmp while our DHCP_DROP dismantling is ongoing.)
752 cancel_smach_timers(dsmp
);
753 (void) script_start(dsmp
, isv6
? EVENT_DROP6
: EVENT_DROP
,
754 dhcp_drop
, NULL
, NULL
);
755 break; /* not an immediate function */
758 (void) dhcp_extending(dsmp
);
762 dhcp_optnum_t optnum
;
765 boolean_t did_alloc
= B_FALSE
;
766 PKT_LIST
*ack
= dsmp
->dsm_ack
;
770 * verify the request makes sense.
773 if (iap
->ia_request
->data_type
!= DHCP_TYPE_OPTNUM
||
774 iap
->ia_request
->data_length
!= sizeof (dhcp_optnum_t
)) {
775 send_error_reply(iap
, DHCP_IPC_E_PROTO
);
779 (void) memcpy(&optnum
, iap
->ia_request
->buffer
,
780 sizeof (dhcp_optnum_t
));
783 switch (optnum
.category
) {
785 case DSYM_SITE
: /* FALLTHRU */
787 for (i
= 0; i
< dsmp
->dsm_pillen
; i
++) {
788 if (dsmp
->dsm_pil
[i
] == optnum
.code
)
791 if (i
< dsmp
->dsm_pillen
)
794 opt
= dhcpv6_pkt_option(ack
, NULL
, optnum
.code
,
797 if (optnum
.code
<= DHCP_LAST_OPT
)
798 opt
= ack
->opts
[optnum
.code
];
804 dhcpv6_option_t
*d6o
;
808 * Look through vendor options to find our
813 d6o
= dhcpv6_pkt_option(ack
, d6o
,
814 DHCPV6_OPT_VENDOR_OPT
, &optlen
);
817 optlen
-= sizeof (*d6o
);
818 if (optlen
< sizeof (ent
))
820 (void) memcpy(&ent
, d6o
+ 1,
822 if (ntohl(ent
) != DHCPV6_SUN_ENT
)
828 * Now find the requested vendor option
829 * within the vendor options block.
831 opt
= dhcpv6_find_option(
832 (char *)(d6o
+ 1) + sizeof (ent
),
833 optlen
- sizeof (ent
), NULL
,
838 * the test against VS_OPTION_START is broken
839 * up into two tests to avoid compiler warnings
842 if ((optnum
.code
> VS_OPTION_START
||
843 optnum
.code
== VS_OPTION_START
) &&
844 optnum
.code
<= VS_OPTION_END
)
845 opt
= ack
->vs
[optnum
.code
];
851 dhcpv6_message_t
*d6m
=
852 (dhcpv6_message_t
*)ack
->pkt
;
853 dhcpv6_option_t
*d6o
;
855 /* Validate the packet field the user wants */
856 optlen
= optnum
.code
+ optnum
.size
;
857 if (d6m
->d6m_msg_type
==
858 DHCPV6_MSG_RELAY_FORW
||
860 DHCPV6_MSG_RELAY_REPL
) {
861 if (optlen
> sizeof (dhcpv6_relay_t
))
864 if (optlen
> sizeof (*d6m
))
868 opt
= malloc(sizeof (*d6o
) + optnum
.size
);
871 d6o
->d6o_code
= htons(optnum
.code
);
872 d6o
->d6o_len
= htons(optnum
.size
);
873 (void) memcpy(d6o
+ 1, (caddr_t
)d6m
+
874 optnum
.code
, optnum
.size
);
877 if (optnum
.code
+ optnum
.size
> sizeof (PKT
))
881 * + 2 to account for option code and length
884 opt
= malloc(optnum
.size
+ 2);
886 DHCP_OPT
*v4opt
= opt
;
888 v4opt
->len
= optnum
.size
;
889 v4opt
->code
= optnum
.code
;
890 (void) memcpy(v4opt
->value
,
891 (caddr_t
)ack
->pkt
+ optnum
.code
,
897 send_error_reply(iap
, DHCP_IPC_E_MEMORY
);
904 send_error_reply(iap
, DHCP_IPC_E_PROTO
);
909 * return the option payload, if there was one. the "+ 2"
910 * accounts for the option code number and length byte.
915 dhcpv6_option_t d6ov
;
917 (void) memcpy(&d6ov
, opt
, sizeof (d6ov
));
918 optlen
= ntohs(d6ov
.d6o_len
) + sizeof (d6ov
);
920 optlen
= ((DHCP_OPT
*)opt
)->len
+ 2;
922 send_data_reply(iap
, 0, DHCP_TYPE_OPTION
, opt
, optlen
);
927 } else if (ack
!= dsmp
->dsm_orig_ack
) {
929 * There wasn't any definition for the option in the
930 * current ack, so now retry with the original ack if
931 * the original ack is not the current ack.
933 ack
= dsmp
->dsm_orig_ack
;
938 * note that an "okay" response is returned either in
939 * the case of an unknown option or a known option
940 * with no payload. this is okay (for now) since
941 * dhcpinfo checks whether an option is valid before
942 * ever performing ipc with the agent.
951 /* next destination: dhcp_acknak() */
952 break; /* not an immediate function */
955 if (dsmp
->dsm_dflags
& DHCP_IF_FAILED
)
956 send_error_reply(iap
, DHCP_IPC_E_FAILEDIF
);
962 if (dsmp
->dsm_droprelease
)
964 dsmp
->dsm_droprelease
= B_TRUE
;
965 cancel_smach_timers(dsmp
); /* see comment in DHCP_DROP above */
966 (void) script_start(dsmp
, isv6
? EVENT_RELEASE6
:
967 EVENT_RELEASE
, dhcp_release
, "Finished with lease.", NULL
);
968 break; /* not an immediate function */
971 PKT_LIST
*ack
, *oack
;
974 deprecate_leases(dsmp
);
977 * if we have a valid hostconf lying around, then jump
978 * into INIT_REBOOT. if it fails, we'll end up going
979 * through the whole selecting() procedure again.
982 error
= read_hostconf(dsmp
->dsm_name
, plp
, 2, dsmp
->dsm_isv6
);
983 ack
= error
> 0 ? plp
[0] : NULL
;
984 oack
= error
> 1 ? plp
[1] : NULL
;
987 * If the allocation of the old ack fails, that's fine;
988 * continue without it.
994 * As long as we've allocated something, start using it.
997 dsmp
->dsm_orig_ack
= oack
;
999 dhcp_init_reboot(dsmp
);
1000 /* next destination: dhcp_acknak() */
1005 * if not debugging, wait for a few seconds before
1006 * going into SELECTING.
1009 if (debug_level
== 0 && set_start_timer(dsmp
)) {
1010 /* next destination: dhcp_start() */
1013 dhcp_selecting(dsmp
);
1014 /* next destination: dhcp_requesting() */
1020 dhcp_status_t status
;
1023 status
.if_began
= monosec_to_time(dsmp
->dsm_curstart_monosec
);
1026 * We return information on just the first lease as being
1027 * representative of the lot. A better status mechanism is
1030 dlp
= dsmp
->dsm_leases
;
1033 dlp
->dl_lifs
->lif_expire
.dt_start
== DHCP_PERM
) {
1034 status
.if_t1
= DHCP_PERM
;
1035 status
.if_t2
= DHCP_PERM
;
1036 status
.if_lease
= DHCP_PERM
;
1038 status
.if_t1
= status
.if_began
+
1039 dlp
->dl_t1
.dt_start
;
1040 status
.if_t2
= status
.if_began
+
1041 dlp
->dl_t2
.dt_start
;
1042 status
.if_lease
= status
.if_began
+
1043 dlp
->dl_lifs
->lif_expire
.dt_start
;
1046 status
.version
= DHCP_STATUS_VER
;
1047 status
.if_state
= dsmp
->dsm_state
;
1048 status
.if_dflags
= dsmp
->dsm_dflags
;
1049 status
.if_sent
= dsmp
->dsm_sent
;
1050 status
.if_recv
= dsmp
->dsm_received
;
1051 status
.if_bad_offers
= dsmp
->dsm_bad_offers
;
1053 (void) strlcpy(status
.if_name
, dsmp
->dsm_name
, LIFNAMSIZ
);
1055 send_data_reply(iap
, 0, DHCP_TYPE_STATUS
, &status
,
1056 sizeof (dhcp_status_t
));
1063 * check_rtm_addr(): determine if routing socket message matches interface
1066 * input: const struct if_msghdr *: pointer to routing socket message
1067 * int: routing socket message length
1068 * boolean_t: set to B_TRUE if IPv6
1069 * const in6_addr_t *: pointer to IP address
1070 * output: boolean_t: B_TRUE if address is a match
1074 check_rtm_addr(const struct ifa_msghdr
*ifam
, int msglen
, boolean_t isv6
,
1075 const in6_addr_t
*addr
)
1077 const char *cp
, *lim
;
1079 const struct sockaddr
*sa
;
1081 if (!(ifam
->ifam_addrs
& RTA_IFA
))
1084 cp
= (const char *)(ifam
+ 1);
1085 lim
= (const char *)ifam
+ msglen
;
1086 for (flag
= 1; flag
< RTA_IFA
; flag
<<= 1) {
1087 if (ifam
->ifam_addrs
& flag
) {
1088 /* LINTED: alignment */
1089 sa
= (const struct sockaddr
*)cp
;
1090 if ((const char *)(sa
+ 1) > lim
)
1092 switch (sa
->sa_family
) {
1094 cp
+= sizeof (struct sockaddr_in
);
1097 cp
+= sizeof (struct sockaddr_dl
);
1100 cp
+= sizeof (struct sockaddr_in6
);
1103 cp
+= sizeof (struct sockaddr
);
1109 const struct sockaddr_in6
*sin6
;
1111 /* LINTED: alignment */
1112 sin6
= (const struct sockaddr_in6
*)cp
;
1113 if ((const char *)(sin6
+ 1) > lim
)
1115 if (sin6
->sin6_family
!= AF_INET6
)
1117 return (IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
, addr
));
1119 const struct sockaddr_in
*sinp
;
1122 /* LINTED: alignment */
1123 sinp
= (const struct sockaddr_in
*)cp
;
1124 if ((const char *)(sinp
+ 1) > lim
)
1126 if (sinp
->sin_family
!= AF_INET
)
1128 IN6_V4MAPPED_TO_IPADDR(addr
, v4addr
);
1129 return (sinp
->sin_addr
.s_addr
== v4addr
);
1134 * is_rtm_v6(): determine if routing socket message is IPv6
1136 * input: struct ifa_msghdr *: pointer to routing socket message
1137 * int: message length
1142 is_rtm_v6(const struct ifa_msghdr
*ifam
, int msglen
)
1144 const char *cp
, *lim
;
1146 const struct sockaddr
*sa
;
1148 cp
= (const char *)(ifam
+ 1);
1149 lim
= (const char *)ifam
+ msglen
;
1150 for (flag
= ifam
->ifam_addrs
; flag
!= 0; flag
&= flag
- 1) {
1151 /* LINTED: alignment */
1152 sa
= (const struct sockaddr
*)cp
;
1153 if ((const char *)(sa
+ 1) > lim
)
1155 switch (sa
->sa_family
) {
1159 cp
+= sizeof (struct sockaddr_dl
);
1164 cp
+= sizeof (struct sockaddr
);
1172 * check_lif(): check the state of a given logical interface and its DHCP
1173 * lease. We've been told by the routing socket that the
1174 * corresponding ifIndex has changed. This may mean that DAD has
1175 * completed or failed.
1177 * input: dhcp_lif_t *: pointer to the LIF
1178 * const struct ifa_msghdr *: routing socket message
1179 * int: size of routing socket message
1180 * output: boolean_t: B_TRUE if DAD has completed on this interface
1184 check_lif(dhcp_lif_t
*lif
, const struct ifa_msghdr
*ifam
, int msglen
)
1186 boolean_t isv6
, dad_wait
, unplumb
;
1190 isv6
= lif
->lif_pif
->pif_isv6
;
1191 fd
= isv6
? v6_sock_fd
: v4_sock_fd
;
1194 * Get the real (64 bit) logical interface flags. Note that the
1195 * routing socket message has flags, but these are just the lower 32
1199 (void) memset(&lifr
, 0, sizeof (lifr
));
1200 (void) strlcpy(lifr
.lifr_name
, lif
->lif_name
, sizeof (lifr
.lifr_name
));
1201 if (ioctl(fd
, SIOCGLIFFLAGS
, &lifr
) == -1) {
1203 * Failing to retrieve flags means that the interface is gone.
1204 * It hasn't failed to verify with DAD, but we still have to
1207 lifr
.lifr_flags
= 0;
1208 if (errno
== ENXIO
) {
1209 lif
->lif_plumbed
= B_FALSE
;
1210 dhcpmsg(MSG_INFO
, "%s has been removed; abandoning",
1213 discard_default_routes(lif
->lif_smachs
);
1216 "unable to retrieve interface flags on %s",
1220 } else if (!check_rtm_addr(ifam
, msglen
, isv6
, &lif
->lif_v6addr
)) {
1222 * If the message is not about this logical interface,
1223 * then just ignore it.
1226 } else if (lifr
.lifr_flags
& IFF_DUPLICATE
) {
1227 dhcpmsg(MSG_ERROR
, "interface %s has duplicate address",
1229 lif_mark_decline(lif
, "duplicate address");
1231 (void) open_ip_lif(lif
, INADDR_ANY
, B_TRUE
);
1234 dad_wait
= lif
->lif_dad_wait
;
1236 dhcpmsg(MSG_VERBOSE
, "check_lif: %s has finished DAD",
1238 lif
->lif_dad_wait
= B_FALSE
;
1248 * check_main_lif(): check the state of a main logical interface for a state
1249 * machine. This is used only for DHCPv6.
1251 * input: dhcp_smach_t *: pointer to the state machine
1252 * const struct ifa_msghdr *: routing socket message
1253 * int: size of routing socket message
1254 * output: boolean_t: B_TRUE if LIF is ok.
1258 check_main_lif(dhcp_smach_t
*dsmp
, const struct ifa_msghdr
*ifam
, int msglen
)
1260 dhcp_lif_t
*lif
= dsmp
->dsm_lif
;
1264 * Get the real (64 bit) logical interface flags. Note that the
1265 * routing socket message has flags, but these are just the lower 32
1268 (void) memset(&lifr
, 0, sizeof (lifr
));
1269 (void) strlcpy(lifr
.lifr_name
, lif
->lif_name
, sizeof (lifr
.lifr_name
));
1270 if (ioctl(v6_sock_fd
, SIOCGLIFFLAGS
, &lifr
) == -1) {
1272 * Failing to retrieve flags means that the interface is gone.
1273 * Our state machine is now trash.
1275 if (errno
== ENXIO
) {
1276 dhcpmsg(MSG_INFO
, "%s has been removed; abandoning",
1280 "unable to retrieve interface flags on %s",
1284 } else if (!check_rtm_addr(ifam
, msglen
, B_TRUE
, &lif
->lif_v6addr
)) {
1286 * If the message is not about this logical interface,
1287 * then just ignore it.
1290 } else if (lifr
.lifr_flags
& IFF_DUPLICATE
) {
1291 dhcpmsg(MSG_ERROR
, "interface %s has duplicate address",
1300 * process_link_up_down(): check the state of a physical interface for up/down
1301 * transitions; must go through INIT_REBOOT state if
1304 * input: dhcp_pif_t *: pointer to the physical interface to check
1305 * const struct if_msghdr *: routing socket message
1310 process_link_up_down(dhcp_pif_t
*pif
, const struct if_msghdr
*ifm
)
1317 * If the message implies no change of flags, then we're done; no need
1318 * to check further. Note that if we have multiple state machines on a
1319 * single physical interface, this test keeps us from issuing an ioctl
1322 if ((ifm
->ifm_flags
& IFF_RUNNING
) && pif
->pif_running
||
1323 !(ifm
->ifm_flags
& IFF_RUNNING
) && !pif
->pif_running
)
1327 * We don't know what the real interface flags are, because the
1328 * if_index number is only 16 bits; we must go ask.
1330 isv6
= pif
->pif_isv6
;
1331 fd
= isv6
? v6_sock_fd
: v4_sock_fd
;
1332 (void) memset(&lifr
, 0, sizeof (lifr
));
1333 (void) strlcpy(lifr
.lifr_name
, pif
->pif_name
, sizeof (lifr
.lifr_name
));
1335 if (ioctl(fd
, SIOCGLIFFLAGS
, &lifr
) == -1 ||
1336 !(lifr
.lifr_flags
& IFF_RUNNING
)) {
1338 * If we've lost the interface or it has gone down, then
1339 * nothing special to do; just turn off the running flag.
1341 pif_status(pif
, B_FALSE
);
1344 * Interface has come back up: go through verification process.
1346 pif_status(pif
, B_TRUE
);
1351 * rtsock_event(): fetches routing socket messages and updates internal
1352 * interface state based on those messages.
1354 * input: iu_eh_t *: unused
1355 * int: the routing socket file descriptor
1356 * (other arguments unused)
1362 rtsock_event(iu_eh_t
*ehp
, int fd
, short events
, iu_event_id_t id
, void *arg
)
1364 dhcp_smach_t
*dsmp
, *dsmnext
;
1366 struct ifa_msghdr ifam
;
1367 struct if_msghdr ifm
;
1374 if ((msglen
= read(fd
, &msg
, sizeof (msg
))) <= 0)
1377 /* Note that the routing socket interface index is just 16 bits */
1378 if (msg
.ifm
.ifm_type
== RTM_IFINFO
) {
1379 ifindex
= msg
.ifm
.ifm_index
;
1380 isv6
= (msg
.ifm
.ifm_flags
& IFF_IPV6
) ? B_TRUE
: B_FALSE
;
1381 } else if (msg
.ifam
.ifam_type
== RTM_DELADDR
||
1382 msg
.ifam
.ifam_type
== RTM_NEWADDR
) {
1383 ifindex
= msg
.ifam
.ifam_index
;
1384 isv6
= is_rtm_v6(&msg
.ifam
, msglen
);
1389 for (dsmp
= lookup_smach_by_uindex(ifindex
, NULL
, isv6
);
1390 dsmp
!= NULL
; dsmp
= dsmnext
) {
1392 boolean_t lif_finished
;
1393 boolean_t lease_removed
;
1394 dhcp_lease_t
*dlp
, *dlnext
;
1397 * Note that script_start can call dhcp_drop directly, and
1398 * that will do release_smach.
1400 dsmnext
= lookup_smach_by_uindex(ifindex
, dsmp
, isv6
);
1401 oldstate
= dsmp
->dsm_state
;
1404 * Ignore state machines that are currently processing drop or
1405 * release; there is nothing more we can do for them.
1407 if (dsmp
->dsm_droprelease
)
1411 * Look for link up/down notifications. These occur on a
1412 * physical interface basis.
1414 if (msg
.ifm
.ifm_type
== RTM_IFINFO
) {
1415 process_link_up_down(dsmp
->dsm_lif
->lif_pif
, &msg
.ifm
);
1420 * Since we cannot trust the flags reported by the routing
1421 * socket (they're just 32 bits -- and thus never include
1422 * IFF_DUPLICATE), and we can't trust the ifindex (it's only 16
1423 * bits and also doesn't reflect the alias in use), we get
1424 * flags on all matching interfaces, and go by that.
1426 lif_finished
= B_FALSE
;
1427 lease_removed
= B_FALSE
;
1428 for (dlp
= dsmp
->dsm_leases
; dlp
!= NULL
; dlp
= dlnext
) {
1429 dhcp_lif_t
*lif
, *lifnext
;
1430 uint_t nlifs
= dlp
->dl_nlifs
;
1432 dlnext
= dlp
->dl_next
;
1433 for (lif
= dlp
->dl_lifs
; lif
!= NULL
&& nlifs
> 0;
1434 lif
= lifnext
, nlifs
--) {
1435 lifnext
= lif
->lif_next
;
1436 if (check_lif(lif
, &msg
.ifam
, msglen
)) {
1437 dsmp
->dsm_lif_wait
--;
1438 lif_finished
= B_TRUE
;
1441 if (dlp
->dl_nlifs
== 0) {
1443 lease_removed
= B_TRUE
;
1447 if ((isv6
&& !check_main_lif(dsmp
, &msg
.ifam
, msglen
)) ||
1448 (!isv6
&& !verify_lif(dsmp
->dsm_lif
))) {
1449 finished_smach(dsmp
, DHCP_IPC_E_INVIF
);
1454 * Ignore this state machine if nothing interesting has
1457 if (!lif_finished
&& dsmp
->dsm_lif_down
== 0 &&
1458 (dsmp
->dsm_leases
!= NULL
|| !lease_removed
))
1462 * If we're still waiting for DAD to complete on some of the
1463 * configured LIFs, then don't send a response.
1465 if (dsmp
->dsm_lif_wait
!= 0) {
1466 dhcpmsg(MSG_VERBOSE
, "rtsock_event: %s still has %d "
1467 "LIFs waiting on DAD", dsmp
->dsm_name
,
1468 dsmp
->dsm_lif_wait
);
1473 * If we have some failed LIFs, then handle them now. We'll
1474 * remove them from the list. Any leases that become empty are
1475 * also removed as part of the decline-generation process.
1477 if (dsmp
->dsm_lif_down
!= 0)
1478 send_declines(dsmp
);
1480 if (dsmp
->dsm_leases
== NULL
) {
1481 dsmp
->dsm_bad_offers
++;
1483 * For DHCPv6, we'll process the restart once we're
1484 * done sending Decline messages, because these are
1485 * supposed to be acknowledged. With DHCPv4, there's
1486 * no acknowledgment for a DECLINE, so after sending
1487 * it, we just restart right away.
1489 if (!dsmp
->dsm_isv6
) {
1490 dhcpmsg(MSG_VERBOSE
, "rtsock_event: %s has no "
1491 "LIFs left", dsmp
->dsm_name
);
1496 * If we're now up on at least some of the leases and
1497 * we were waiting for that, then kick off the rest of
1498 * configuration. Lease validation and DAD are done.
1500 dhcpmsg(MSG_VERBOSE
, "rtsock_event: all LIFs verified "
1501 "on %s in %s state", dsmp
->dsm_name
,
1502 dhcp_state_to_string(oldstate
));
1503 if (oldstate
== PRE_BOUND
||
1504 oldstate
== ADOPTING
)
1505 dhcp_bound_complete(dsmp
);
1506 if (oldstate
== ADOPTING
)
1507 dhcp_adopt_complete(dsmp
);
1513 * check_cmd_allowed(): check whether the requested command is allowed in the
1516 * input: DHCPSTATE: current state
1517 * dhcp_ipc_type_t: requested command
1518 * output: boolean_t: B_TRUE if command is allowed in this state
1522 check_cmd_allowed(DHCPSTATE state
, dhcp_ipc_type_t cmd
)
1524 return (ipc_cmd_allowed
[state
][cmd
] != 0);
1528 is_iscsi_active(void)
1533 if ((fd
= open(ISCSI_DRIVER_DEVCTL
, O_RDONLY
)) != -1) {
1534 if (ioctl(fd
, ISCSI_IS_ACTIVE
, &active
) != 0)
1539 return (active
!= 0);