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>
49 #include "script_handler.h"
54 #include "interface.h"
58 #define TEXT_DOMAIN "SYS_TEST"
61 iu_timer_id_t inactivity_id
;
69 static boolean_t shutdown_started
= B_FALSE
;
70 static boolean_t do_adopt
= B_FALSE
;
71 static unsigned int debug_level
= 0;
72 static iu_eh_callback_t accept_event
, ipc_event
, rtsock_event
;
75 * The ipc_cmd_allowed[] table indicates which IPC commands are allowed in
76 * which states; a non-zero value indicates the command is permitted.
78 * START is permitted if the state machine is fresh, or if we are in the
79 * process of trying to obtain a lease (as a convenience to save the
80 * administrator from having to do an explicit DROP). EXTEND, RELEASE, and
81 * GET_TAG require a lease to be obtained in order to make sense. INFORM is
82 * permitted if the interface is fresh or has an INFORM in progress or
83 * previously done on it -- otherwise a DROP or RELEASE is first required.
84 * PING and STATUS always make sense and thus are always permitted, as is DROP
85 * in order to permit the administrator to always bail out.
87 static int ipc_cmd_allowed
[DHCP_NSTATES
][DHCP_NIPC
] = {
95 /* INIT */ { 1, 0, 1, 0, 1, 1, 1, 0 },
96 /* SELECTING */ { 1, 0, 1, 0, 1, 1, 0, 0 },
97 /* REQUESTING */ { 1, 0, 1, 0, 1, 1, 0, 0 },
98 /* PRE_BOUND */ { 1, 1, 1, 1, 0, 1, 0, 1 },
99 /* BOUND */ { 1, 1, 1, 1, 0, 1, 0, 1 },
100 /* RENEWING */ { 1, 1, 1, 1, 0, 1, 0, 1 },
101 /* REBINDING */ { 1, 1, 1, 1, 0, 1, 0, 1 },
102 /* INFORMATION */ { 1, 0, 1, 0, 1, 1, 1, 1 },
103 /* INIT_REBOOT */ { 1, 0, 1, 1, 1, 1, 0, 0 },
104 /* ADOPTING */ { 1, 0, 1, 1, 0, 1, 0, 0 },
105 /* INFORM_SENT */ { 1, 0, 1, 0, 1, 1, 1, 0 },
106 /* DECLINING */ { 1, 1, 1, 1, 0, 1, 0, 1 },
107 /* RELEASING */ { 1, 0, 1, 0, 0, 1, 0, 1 },
110 #define CMD_ISPRIV 0x1 /* Command requires privileges */
111 #define CMD_CREATE 0x2 /* Command creates an interface */
112 #define CMD_BOOTP 0x4 /* Command is valid with BOOTP */
113 #define CMD_IMMED 0x8 /* Reply is immediate (no BUSY state) */
115 static uint_t ipc_cmd_flags
[DHCP_NIPC
] = {
116 /* DHCP_DROP */ CMD_ISPRIV
|CMD_BOOTP
,
117 /* DHCP_EXTEND */ CMD_ISPRIV
,
118 /* DHCP_PING */ CMD_BOOTP
|CMD_IMMED
,
119 /* DHCP_RELEASE */ CMD_ISPRIV
,
120 /* DHCP_START */ CMD_CREATE
|CMD_ISPRIV
|CMD_BOOTP
,
121 /* DHCP_STATUS */ CMD_BOOTP
|CMD_IMMED
,
122 /* DHCP_INFORM */ CMD_CREATE
|CMD_ISPRIV
,
123 /* DHCP_GET_TAG */ CMD_BOOTP
|CMD_IMMED
126 static boolean_t
is_iscsi_active(void);
129 main(int argc
, char **argv
)
131 boolean_t is_daemon
= B_TRUE
;
132 boolean_t is_verbose
;
135 int aware
= RTAW_UNDER_IPMP
;
138 debug_level
= df_get_int("", B_FALSE
, DF_DEBUG_LEVEL
);
139 is_verbose
= df_get_bool("", B_FALSE
, DF_VERBOSE
);
142 * -l is ignored for compatibility with old agent.
145 while ((c
= getopt(argc
, argv
, "vd:l:fa")) != EOF
) {
151 grandparent
= getpid();
155 debug_level
= strtoul(optarg
, NULL
, 0);
167 (void) fprintf(stderr
, "usage: %s [-a] [-d n] [-f] [-v]"
169 return (EXIT_FAILURE
);
176 (void) setlocale(LC_ALL
, "");
177 (void) textdomain(TEXT_DOMAIN
);
179 if (geteuid() != 0) {
180 dhcpmsg_init(argv
[0], B_FALSE
, is_verbose
, debug_level
);
181 dhcpmsg(MSG_ERROR
, "must be super-user");
183 return (EXIT_FAILURE
);
186 if (is_daemon
&& daemonize() == 0) {
187 dhcpmsg_init(argv
[0], B_FALSE
, is_verbose
, debug_level
);
188 dhcpmsg(MSG_ERR
, "cannot become daemon, exiting");
190 return (EXIT_FAILURE
);
194 * Seed the random number generator, since we're going to need it
195 * to set transaction id's and for exponential backoff.
197 srand48(gethrtime() ^ gethostid() ^ getpid());
199 dhcpmsg_init(argv
[0], is_daemon
, is_verbose
, debug_level
);
200 (void) atexit(dhcpmsg_fini
);
205 if (eh
== NULL
|| tq
== NULL
) {
207 dhcpmsg(MSG_ERR
, "cannot create timer queue or event handler");
208 return (EXIT_FAILURE
);
212 * ignore most signals that could be reasonably generated.
215 (void) signal(SIGTERM
, graceful_shutdown
);
216 (void) signal(SIGQUIT
, graceful_shutdown
);
217 (void) signal(SIGPIPE
, SIG_IGN
);
218 (void) signal(SIGUSR1
, SIG_IGN
);
219 (void) signal(SIGUSR2
, SIG_IGN
);
220 (void) signal(SIGINT
, SIG_IGN
);
221 (void) signal(SIGHUP
, SIG_IGN
);
222 (void) signal(SIGCHLD
, SIG_IGN
);
225 * upon SIGTHAW we need to refresh any non-infinite leases.
228 (void) iu_eh_register_signal(eh
, SIGTHAW
, refresh_smachs
, NULL
);
230 class_id
= get_class_id();
231 if (class_id
!= NULL
)
232 class_id_len
= strlen(class_id
);
234 dhcpmsg(MSG_WARNING
, "get_class_id failed, continuing "
235 "with no vendor class id");
238 * the inactivity timer is enabled any time there are no
239 * interfaces under DHCP control. if DHCP_INACTIVITY_WAIT
240 * seconds transpire without an interface under DHCP control,
241 * the agent shuts down.
244 inactivity_id
= iu_schedule_timer(tq
, DHCP_INACTIVITY_WAIT
,
245 inactivity_shutdown
, NULL
);
248 * max out the number available descriptors, just in case..
251 rl
.rlim_cur
= RLIM_INFINITY
;
252 rl
.rlim_max
= RLIM_INFINITY
;
253 if (setrlimit(RLIMIT_NOFILE
, &rl
) == -1)
254 dhcpmsg(MSG_ERR
, "setrlimit failed");
256 (void) enable_extended_FILE_stdio(-1, -1);
259 * Create and bind default IP sockets used to control interfaces and to
260 * catch stray packets.
263 if (!dhcp_ip_default())
264 return (EXIT_FAILURE
);
267 * create the ipc channel that the agent will listen for
268 * requests on, and register it with the event handler so that
269 * `accept_event' will be called back.
272 switch (dhcp_ipc_init(&ipc_fd
)) {
277 case DHCP_IPC_E_BIND
:
278 dhcpmsg(MSG_ERROR
, "dhcp_ipc_init: cannot bind to port "
279 "%i (agent already running?)", IPPORT_DHCPAGENT
);
280 return (EXIT_FAILURE
);
283 dhcpmsg(MSG_ERROR
, "dhcp_ipc_init failed");
284 return (EXIT_FAILURE
);
287 if (iu_register_event(eh
, ipc_fd
, POLLIN
, accept_event
, 0) == -1) {
288 dhcpmsg(MSG_ERR
, "cannot register ipc fd for messages");
289 return (EXIT_FAILURE
);
293 * Create the global routing socket. This is used for monitoring
294 * interface transitions, so that we learn about the kernel's Duplicate
295 * Address Detection status, and for inserting and removing default
296 * routes as learned from DHCP servers. Both v4 and v6 are handed
297 * with this one socket.
299 rtsock_fd
= socket(PF_ROUTE
, SOCK_RAW
, 0);
300 if (rtsock_fd
== -1) {
301 dhcpmsg(MSG_ERR
, "cannot open routing socket");
302 return (EXIT_FAILURE
);
306 * We're IPMP-aware and can manage IPMP test addresses, so issue
307 * RT_AWARE to get routing socket messages for interfaces under IPMP.
309 if (setsockopt(rtsock_fd
, SOL_ROUTE
, RT_AWARE
, &aware
,
310 sizeof (aware
)) == -1) {
311 dhcpmsg(MSG_ERR
, "cannot set RT_AWARE on routing socket");
312 return (EXIT_FAILURE
);
315 if (iu_register_event(eh
, rtsock_fd
, POLLIN
, rtsock_event
, 0) == -1) {
316 dhcpmsg(MSG_ERR
, "cannot register routing socket for messages");
317 return (EXIT_FAILURE
);
321 * if the -a (adopt) option was specified, try to adopt the
322 * kernel-managed interface before we start.
325 if (do_adopt
&& !dhcp_adopt())
326 return (EXIT_FAILURE
);
329 * For DHCPv6, we own all of the interfaces marked DHCPRUNNING. As
330 * we're starting operation here, if there are any of those interfaces
331 * lingering around, they're strays, and need to be removed.
333 * It might be nice to save these addresses off somewhere -- for both
334 * v4 and v6 -- and use them as hints for later negotiation.
339 * enter the main event loop; this is where all the real work
340 * takes place (through registering events and scheduling timers).
341 * this function only returns when the agent is shutting down.
344 switch (iu_handle_events(eh
, tq
)) {
347 dhcpmsg(MSG_WARNING
, "iu_handle_events exited abnormally");
350 case DHCP_REASON_INACTIVITY
:
351 dhcpmsg(MSG_INFO
, "no interfaces to manage, shutting down...");
354 case DHCP_REASON_TERMINATE
:
355 dhcpmsg(MSG_INFO
, "received SIGTERM, shutting down...");
358 case DHCP_REASON_SIGNAL
:
359 dhcpmsg(MSG_WARNING
, "received unexpected signal, shutting "
364 (void) iu_eh_unregister_signal(eh
, SIGTHAW
, NULL
);
369 return (EXIT_SUCCESS
);
373 * drain_script(): event loop callback during shutdown
375 * input: eh_t *: unused
377 * output: boolean_t: B_TRUE if event loop should exit; B_FALSE otherwise
382 drain_script(iu_eh_t
*ehp
, void *arg
)
384 if (shutdown_started
== B_FALSE
) {
385 shutdown_started
= B_TRUE
;
387 * Check if the system is diskless client and/or
388 * there are active iSCSI sessions
390 * Do not drop the lease, or the system will be
391 * unable to sync(dump) through nfs/iSCSI driver
393 if (!do_adopt
&& !is_iscsi_active()) {
397 return (script_count
== 0);
401 * accept_event(): accepts a new connection on the ipc socket and registers
402 * to receive its messages with the event handler
404 * input: iu_eh_t *: unused
405 * int: the file descriptor in the iu_eh_t * the connection came in on
406 * (other arguments unused)
412 accept_event(iu_eh_t
*ehp
, int fd
, short events
, iu_event_id_t id
, void *arg
)
417 if (dhcp_ipc_accept(fd
, &client_fd
, &is_priv
) != 0) {
418 dhcpmsg(MSG_ERR
, "accept_event: accept on ipc socket");
422 if (iu_register_event(eh
, client_fd
, POLLIN
, ipc_event
,
423 (void *)is_priv
) == -1) {
424 dhcpmsg(MSG_ERROR
, "accept_event: cannot register ipc socket "
430 * ipc_event(): processes incoming ipc requests
432 * input: iu_eh_t *: unused
433 * int: the file descriptor in the iu_eh_t * the request came in on
435 * iu_event_id_t: event ID
436 * void *: indicates whether the request is from a privileged client
442 ipc_event(iu_eh_t
*ehp
, int fd
, short events
, iu_event_id_t id
, void *arg
)
444 ipc_action_t ia
, *iap
;
446 int error
, is_priv
= (int)arg
;
449 boolean_t dsm_created
= B_FALSE
;
451 ipc_action_init(&ia
);
452 error
= dhcp_ipc_recv_request(fd
, &ia
.ia_request
,
453 DHCP_IPC_REQUEST_WAIT
);
454 if (error
!= DHCP_IPC_SUCCESS
) {
455 if (error
!= DHCP_IPC_E_EOF
) {
457 "ipc_event: dhcp_ipc_recv_request failed: %s",
458 dhcp_ipc_strerror(error
));
460 dhcpmsg(MSG_DEBUG
, "ipc_event: connection closed");
462 if ((dsmp
= lookup_smach_by_event(id
)) != NULL
) {
463 ipc_action_finish(dsmp
, error
);
465 (void) iu_unregister_event(eh
, id
, NULL
);
466 (void) dhcp_ipc_close(fd
);
471 /* Fill in temporary ipc_action structure for utility functions */
472 ia
.ia_cmd
= DHCP_IPC_CMD(ia
.ia_request
->message_type
);
476 if (ia
.ia_cmd
>= DHCP_NIPC
) {
478 "ipc_event: invalid command (%s) attempted on %s",
479 dhcp_ipc_type_to_string(ia
.ia_cmd
), ia
.ia_request
->ifname
);
480 send_error_reply(&ia
, DHCP_IPC_E_CMD_UNKNOWN
);
484 /* return EPERM for any of the privileged actions */
486 if (!is_priv
&& (ipc_cmd_flags
[ia
.ia_cmd
] & CMD_ISPRIV
)) {
488 "ipc_event: privileged ipc command (%s) attempted on %s",
489 dhcp_ipc_type_to_string(ia
.ia_cmd
), ia
.ia_request
->ifname
);
490 send_error_reply(&ia
, DHCP_IPC_E_PERM
);
495 * Try to locate the state machine associated with this command. If
496 * the command is DHCP_START or DHCP_INFORM and there isn't a state
497 * machine already, make one (there may already be one from a previous
498 * failed attempt to START or INFORM). Otherwise, verify the reference
501 * The interface name may be blank. In that case, we look up the
502 * primary interface, and the requested type (v4 or v6) doesn't matter.
505 isv6
= (ia
.ia_request
->message_type
& DHCP_V6
) != 0;
506 ifname
= ia
.ia_request
->ifname
;
508 dsmp
= primary_smach(isv6
);
510 dsmp
= lookup_smach(ifname
, isv6
);
513 /* Note that verify_smach drops a reference */
515 if (!verify_smach(dsmp
))
521 * If the user asked for the primary DHCP interface by giving
522 * an empty string and there is no primary, then check if we're
523 * handling dhcpinfo. If so, then simulate primary selection.
524 * Otherwise, report failure.
526 if (ifname
[0] == '\0') {
527 if (ia
.ia_cmd
== DHCP_GET_TAG
)
528 dsmp
= info_primary_smach(isv6
);
530 error
= DHCP_IPC_E_NOPRIMARY
;
533 * If there's no interface, and we're starting up, then create
534 * it now, along with a state machine for it. Note that if
535 * insert_smach fails, it discards the LIF reference.
537 } else if (ipc_cmd_flags
[ia
.ia_cmd
] & CMD_CREATE
) {
540 lif
= attach_lif(ifname
, isv6
, &error
);
542 (dsmp
= insert_smach(lif
, &error
)) != NULL
) {
544 * Get client ID for logical interface. (V4
545 * only, because V6 plumbs its own interfaces.)
547 error
= get_smach_cid(dsmp
);
548 if (error
!= DHCP_IPC_SUCCESS
) {
552 dsm_created
= (dsmp
!= NULL
);
556 * Otherwise, this is an operation on an unknown interface.
559 error
= DHCP_IPC_E_UNKIF
;
562 send_error_reply(&ia
, error
);
568 * If this is a request for DHCP to manage a lease on an address,
569 * ensure that IFF_DHCPRUNNING is set (we don't set this when the lif
570 * is created because the lif may have been created for INFORM).
572 if (ia
.ia_cmd
== DHCP_START
&&
573 (error
= set_lif_dhcp(dsmp
->dsm_lif
)) != DHCP_IPC_SUCCESS
) {
576 send_error_reply(&ia
, error
);
580 if ((dsmp
->dsm_dflags
& DHCP_IF_BOOTP
) &&
581 !(ipc_cmd_flags
[ia
.ia_cmd
] & CMD_BOOTP
)) {
582 dhcpmsg(MSG_ERROR
, "command %s not valid for BOOTP on %s",
583 dhcp_ipc_type_to_string(ia
.ia_cmd
), dsmp
->dsm_name
);
584 send_error_reply(&ia
, DHCP_IPC_E_BOOTP
);
589 * verify that the state machine is in a state which will allow the
590 * command. we do this up front so that we can return an error
591 * *before* needlessly cancelling an in-progress transaction.
594 if (!check_cmd_allowed(dsmp
->dsm_state
, ia
.ia_cmd
)) {
596 "in state %s; not allowing %s command on %s",
597 dhcp_state_to_string(dsmp
->dsm_state
),
598 dhcp_ipc_type_to_string(ia
.ia_cmd
), dsmp
->dsm_name
);
599 send_error_reply(&ia
,
600 ia
.ia_cmd
== DHCP_START
&& dsmp
->dsm_state
!= INIT
?
601 DHCP_IPC_E_RUNNING
: DHCP_IPC_E_OUTSTATE
);
605 dhcpmsg(MSG_DEBUG
, "in state %s; allowing %s command on %s",
606 dhcp_state_to_string(dsmp
->dsm_state
),
607 dhcp_ipc_type_to_string(ia
.ia_cmd
), dsmp
->dsm_name
);
609 if ((ia
.ia_request
->message_type
& DHCP_PRIMARY
) && is_priv
)
613 * The current design dictates that there can be only one outstanding
614 * transaction per state machine -- this simplifies the code
615 * considerably and also fits well with RFCs 2131 and 3315. It is
616 * worth classifying the different DHCP commands into synchronous
617 * (those which we will handle now and reply to immediately) and
618 * asynchronous (those which require transactions and will be completed
619 * at an indeterminate time in the future):
621 * DROP: removes the agent's management of a state machine.
622 * asynchronous as the script program may be invoked.
624 * PING: checks to see if the agent has a named state machine.
625 * synchronous, since no packets need to be sent
626 * to the DHCP server.
628 * STATUS: returns information about a state machine.
629 * synchronous, since no packets need to be sent
630 * to the DHCP server.
632 * RELEASE: releases the agent's management of a state machine
633 * and brings the associated interfaces down. asynchronous
634 * as the script program may be invoked.
636 * EXTEND: renews a lease. asynchronous, since the agent
637 * needs to wait for an ACK, etc.
639 * START: starts DHCP on a named state machine. asynchronous since
640 * the agent needs to wait for OFFERs, ACKs, etc.
642 * INFORM: obtains configuration parameters for the system using
643 * externally configured interface. asynchronous, since the
644 * agent needs to wait for an ACK.
646 * Notice that EXTEND, INFORM, START, DROP and RELEASE are
647 * asynchronous. Notice also that asynchronous commands may occur from
648 * within the agent -- for instance, the agent will need to do implicit
649 * EXTENDs to extend the lease. In order to make the code simpler, the
650 * following rules apply for asynchronous commands:
652 * There can only be one asynchronous command at a time per state
653 * machine. The current asynchronous command is managed by the async_*
654 * api: async_start(), async_finish(), and async_cancel().
655 * async_start() starts management of a new asynchronous command on an
656 * state machine, which should only be done after async_cancel() to
657 * terminate a previous command. When the command is completed,
658 * async_finish() should be called.
660 * Asynchronous commands started by a user command have an associated
661 * ipc_action which provides the agent with information for how to get
662 * in touch with the user command when the action completes. These
663 * ipc_action records also have an associated timeout which may be
664 * infinite. ipc_action_start() should be called when starting an
665 * asynchronous command requested by a user, which sets up the timer
666 * and keeps track of the ipc information (file descriptor, request
667 * type). When the asynchronous command completes, ipc_action_finish()
668 * should be called to return a command status code to the user and
669 * close the ipc connection). If the command does not complete before
670 * the timer fires, ipc_action_timeout() is called which closes the ipc
671 * connection and returns DHCP_IPC_E_TIMEOUT to the user. Note that
672 * independent of ipc_action_timeout(), ipc_action_finish() should be
675 * on a case-by-case basis, here is what happens (per state machine):
677 * o When an asynchronous command is requested, then
678 * async_cancel() is called to terminate any non-user
679 * action in progress. If there's a user action running,
680 * the user command is sent DHCP_IPC_E_PEND.
682 * o otherwise, the the transaction is started with
683 * async_start(). if the transaction is on behalf
684 * of a user, ipc_action_start() is called to keep
685 * track of the ipc information and set up the
688 * o if the command completes normally and before a
689 * timeout fires, then async_finish() is called.
690 * if there was an associated ipc_action,
691 * ipc_action_finish() is called to complete it.
693 * o if the command fails before a timeout fires, then
694 * async_finish() is called, and the state machine is
695 * is returned to a known state based on the command.
696 * if there was an associated ipc_action,
697 * ipc_action_finish() is called to complete it.
699 * o if the ipc_action timer fires before command
700 * completion, then DHCP_IPC_E_TIMEOUT is returned to
701 * the user. however, the transaction continues to
702 * be carried out asynchronously.
705 if (ipc_cmd_flags
[ia
.ia_cmd
] & CMD_IMMED
) {
707 * Only immediate commands (ping, status, get_tag) need to
708 * worry about freeing ia through one of the reply functions
714 * if shutdown request has been received, send back an error.
716 if (shutdown_started
) {
717 send_error_reply(&ia
, DHCP_IPC_E_OUTSTATE
);
721 if (dsmp
->dsm_dflags
& DHCP_IF_BUSY
) {
722 send_error_reply(&ia
, DHCP_IPC_E_PEND
);
726 if (!ipc_action_start(dsmp
, &ia
)) {
727 dhcpmsg(MSG_WARNING
, "ipc_event: ipc_action_start "
728 "failed for %s", dsmp
->dsm_name
);
729 send_error_reply(&ia
, DHCP_IPC_E_MEMORY
);
733 /* Action structure consumed by above function */
737 switch (iap
->ia_cmd
) {
740 if (dsmp
->dsm_droprelease
)
742 dsmp
->dsm_droprelease
= B_TRUE
;
745 * Ensure that a timer associated with the existing state
746 * doesn't pop while we're waiting for the script to complete.
747 * (If so, chaos can result -- e.g., a timer causes us to end
748 * up in dhcp_selecting() would start acquiring a new lease on
749 * dsmp while our DHCP_DROP dismantling is ongoing.)
751 cancel_smach_timers(dsmp
);
752 (void) script_start(dsmp
, isv6
? EVENT_DROP6
: EVENT_DROP
,
753 dhcp_drop
, NULL
, NULL
);
754 break; /* not an immediate function */
757 (void) dhcp_extending(dsmp
);
761 dhcp_optnum_t optnum
;
764 boolean_t did_alloc
= B_FALSE
;
765 PKT_LIST
*ack
= dsmp
->dsm_ack
;
769 * verify the request makes sense.
772 if (iap
->ia_request
->data_type
!= DHCP_TYPE_OPTNUM
||
773 iap
->ia_request
->data_length
!= sizeof (dhcp_optnum_t
)) {
774 send_error_reply(iap
, DHCP_IPC_E_PROTO
);
778 (void) memcpy(&optnum
, iap
->ia_request
->buffer
,
779 sizeof (dhcp_optnum_t
));
782 switch (optnum
.category
) {
784 case DSYM_SITE
: /* FALLTHRU */
786 for (i
= 0; i
< dsmp
->dsm_pillen
; i
++) {
787 if (dsmp
->dsm_pil
[i
] == optnum
.code
)
790 if (i
< dsmp
->dsm_pillen
)
793 opt
= dhcpv6_pkt_option(ack
, NULL
, optnum
.code
,
796 if (optnum
.code
<= DHCP_LAST_OPT
)
797 opt
= ack
->opts
[optnum
.code
];
803 dhcpv6_option_t
*d6o
;
807 * Look through vendor options to find our
812 d6o
= dhcpv6_pkt_option(ack
, d6o
,
813 DHCPV6_OPT_VENDOR_OPT
, &optlen
);
816 optlen
-= sizeof (*d6o
);
817 if (optlen
< sizeof (ent
))
819 (void) memcpy(&ent
, d6o
+ 1,
821 if (ntohl(ent
) != DHCPV6_SUN_ENT
)
827 * Now find the requested vendor option
828 * within the vendor options block.
830 opt
= dhcpv6_find_option(
831 (char *)(d6o
+ 1) + sizeof (ent
),
832 optlen
- sizeof (ent
), NULL
,
837 * the test against VS_OPTION_START is broken
838 * up into two tests to avoid compiler warnings
841 if ((optnum
.code
> VS_OPTION_START
||
842 optnum
.code
== VS_OPTION_START
) &&
843 optnum
.code
<= VS_OPTION_END
)
844 opt
= ack
->vs
[optnum
.code
];
850 dhcpv6_message_t
*d6m
=
851 (dhcpv6_message_t
*)ack
->pkt
;
852 dhcpv6_option_t
*d6o
;
854 /* Validate the packet field the user wants */
855 optlen
= optnum
.code
+ optnum
.size
;
856 if (d6m
->d6m_msg_type
==
857 DHCPV6_MSG_RELAY_FORW
||
859 DHCPV6_MSG_RELAY_REPL
) {
860 if (optlen
> sizeof (dhcpv6_relay_t
))
863 if (optlen
> sizeof (*d6m
))
867 opt
= malloc(sizeof (*d6o
) + optnum
.size
);
870 d6o
->d6o_code
= htons(optnum
.code
);
871 d6o
->d6o_len
= htons(optnum
.size
);
872 (void) memcpy(d6o
+ 1, (caddr_t
)d6m
+
873 optnum
.code
, optnum
.size
);
876 if (optnum
.code
+ optnum
.size
> sizeof (PKT
))
880 * + 2 to account for option code and length
883 opt
= malloc(optnum
.size
+ 2);
885 DHCP_OPT
*v4opt
= opt
;
887 v4opt
->len
= optnum
.size
;
888 v4opt
->code
= optnum
.code
;
889 (void) memcpy(v4opt
->value
,
890 (caddr_t
)ack
->pkt
+ optnum
.code
,
896 send_error_reply(iap
, DHCP_IPC_E_MEMORY
);
903 send_error_reply(iap
, DHCP_IPC_E_PROTO
);
908 * return the option payload, if there was one. the "+ 2"
909 * accounts for the option code number and length byte.
914 dhcpv6_option_t d6ov
;
916 (void) memcpy(&d6ov
, opt
, sizeof (d6ov
));
917 optlen
= ntohs(d6ov
.d6o_len
) + sizeof (d6ov
);
919 optlen
= ((DHCP_OPT
*)opt
)->len
+ 2;
921 send_data_reply(iap
, 0, DHCP_TYPE_OPTION
, opt
, optlen
);
926 } else if (ack
!= dsmp
->dsm_orig_ack
) {
928 * There wasn't any definition for the option in the
929 * current ack, so now retry with the original ack if
930 * the original ack is not the current ack.
932 ack
= dsmp
->dsm_orig_ack
;
937 * note that an "okay" response is returned either in
938 * the case of an unknown option or a known option
939 * with no payload. this is okay (for now) since
940 * dhcpinfo checks whether an option is valid before
941 * ever performing ipc with the agent.
950 /* next destination: dhcp_acknak() */
951 break; /* not an immediate function */
954 if (dsmp
->dsm_dflags
& DHCP_IF_FAILED
)
955 send_error_reply(iap
, DHCP_IPC_E_FAILEDIF
);
961 if (dsmp
->dsm_droprelease
)
963 dsmp
->dsm_droprelease
= B_TRUE
;
964 cancel_smach_timers(dsmp
); /* see comment in DHCP_DROP above */
965 (void) script_start(dsmp
, isv6
? EVENT_RELEASE6
:
966 EVENT_RELEASE
, dhcp_release
, "Finished with lease.", NULL
);
967 break; /* not an immediate function */
970 PKT_LIST
*ack
, *oack
;
973 deprecate_leases(dsmp
);
976 * if we have a valid hostconf lying around, then jump
977 * into INIT_REBOOT. if it fails, we'll end up going
978 * through the whole selecting() procedure again.
981 error
= read_hostconf(dsmp
->dsm_name
, plp
, 2, dsmp
->dsm_isv6
);
982 ack
= error
> 0 ? plp
[0] : NULL
;
983 oack
= error
> 1 ? plp
[1] : NULL
;
986 * If the allocation of the old ack fails, that's fine;
987 * continue without it.
993 * As long as we've allocated something, start using it.
996 dsmp
->dsm_orig_ack
= oack
;
998 dhcp_init_reboot(dsmp
);
999 /* next destination: dhcp_acknak() */
1004 * if not debugging, wait for a few seconds before
1005 * going into SELECTING.
1008 if (debug_level
== 0 && set_start_timer(dsmp
)) {
1009 /* next destination: dhcp_start() */
1012 dhcp_selecting(dsmp
);
1013 /* next destination: dhcp_requesting() */
1019 dhcp_status_t status
;
1022 status
.if_began
= monosec_to_time(dsmp
->dsm_curstart_monosec
);
1025 * We return information on just the first lease as being
1026 * representative of the lot. A better status mechanism is
1029 dlp
= dsmp
->dsm_leases
;
1032 dlp
->dl_lifs
->lif_expire
.dt_start
== DHCP_PERM
) {
1033 status
.if_t1
= DHCP_PERM
;
1034 status
.if_t2
= DHCP_PERM
;
1035 status
.if_lease
= DHCP_PERM
;
1037 status
.if_t1
= status
.if_began
+
1038 dlp
->dl_t1
.dt_start
;
1039 status
.if_t2
= status
.if_began
+
1040 dlp
->dl_t2
.dt_start
;
1041 status
.if_lease
= status
.if_began
+
1042 dlp
->dl_lifs
->lif_expire
.dt_start
;
1045 status
.version
= DHCP_STATUS_VER
;
1046 status
.if_state
= dsmp
->dsm_state
;
1047 status
.if_dflags
= dsmp
->dsm_dflags
;
1048 status
.if_sent
= dsmp
->dsm_sent
;
1049 status
.if_recv
= dsmp
->dsm_received
;
1050 status
.if_bad_offers
= dsmp
->dsm_bad_offers
;
1052 (void) strlcpy(status
.if_name
, dsmp
->dsm_name
, LIFNAMSIZ
);
1054 send_data_reply(iap
, 0, DHCP_TYPE_STATUS
, &status
,
1055 sizeof (dhcp_status_t
));
1062 * check_rtm_addr(): determine if routing socket message matches interface
1065 * input: const struct if_msghdr *: pointer to routing socket message
1066 * int: routing socket message length
1067 * boolean_t: set to B_TRUE if IPv6
1068 * const in6_addr_t *: pointer to IP address
1069 * output: boolean_t: B_TRUE if address is a match
1073 check_rtm_addr(const struct ifa_msghdr
*ifam
, int msglen
, boolean_t isv6
,
1074 const in6_addr_t
*addr
)
1076 const char *cp
, *lim
;
1078 const struct sockaddr
*sa
;
1080 if (!(ifam
->ifam_addrs
& RTA_IFA
))
1083 cp
= (const char *)(ifam
+ 1);
1084 lim
= (const char *)ifam
+ msglen
;
1085 for (flag
= 1; flag
< RTA_IFA
; flag
<<= 1) {
1086 if (ifam
->ifam_addrs
& flag
) {
1087 /* LINTED: alignment */
1088 sa
= (const struct sockaddr
*)cp
;
1089 if ((const char *)(sa
+ 1) > lim
)
1091 switch (sa
->sa_family
) {
1093 cp
+= sizeof (struct sockaddr_in
);
1096 cp
+= sizeof (struct sockaddr_dl
);
1099 cp
+= sizeof (struct sockaddr_in6
);
1102 cp
+= sizeof (struct sockaddr
);
1108 const struct sockaddr_in6
*sin6
;
1110 /* LINTED: alignment */
1111 sin6
= (const struct sockaddr_in6
*)cp
;
1112 if ((const char *)(sin6
+ 1) > lim
)
1114 if (sin6
->sin6_family
!= AF_INET6
)
1116 return (IN6_ARE_ADDR_EQUAL(&sin6
->sin6_addr
, addr
));
1118 const struct sockaddr_in
*sinp
;
1121 /* LINTED: alignment */
1122 sinp
= (const struct sockaddr_in
*)cp
;
1123 if ((const char *)(sinp
+ 1) > lim
)
1125 if (sinp
->sin_family
!= AF_INET
)
1127 IN6_V4MAPPED_TO_IPADDR(addr
, v4addr
);
1128 return (sinp
->sin_addr
.s_addr
== v4addr
);
1133 * is_rtm_v6(): determine if routing socket message is IPv6
1135 * input: struct ifa_msghdr *: pointer to routing socket message
1136 * int: message length
1141 is_rtm_v6(const struct ifa_msghdr
*ifam
, int msglen
)
1143 const char *cp
, *lim
;
1145 const struct sockaddr
*sa
;
1147 cp
= (const char *)(ifam
+ 1);
1148 lim
= (const char *)ifam
+ msglen
;
1149 for (flag
= ifam
->ifam_addrs
; flag
!= 0; flag
&= flag
- 1) {
1150 /* LINTED: alignment */
1151 sa
= (const struct sockaddr
*)cp
;
1152 if ((const char *)(sa
+ 1) > lim
)
1154 switch (sa
->sa_family
) {
1158 cp
+= sizeof (struct sockaddr_dl
);
1163 cp
+= sizeof (struct sockaddr
);
1171 * check_lif(): check the state of a given logical interface and its DHCP
1172 * lease. We've been told by the routing socket that the
1173 * corresponding ifIndex has changed. This may mean that DAD has
1174 * completed or failed.
1176 * input: dhcp_lif_t *: pointer to the LIF
1177 * const struct ifa_msghdr *: routing socket message
1178 * int: size of routing socket message
1179 * output: boolean_t: B_TRUE if DAD has completed on this interface
1183 check_lif(dhcp_lif_t
*lif
, const struct ifa_msghdr
*ifam
, int msglen
)
1185 boolean_t isv6
, dad_wait
, unplumb
;
1189 isv6
= lif
->lif_pif
->pif_isv6
;
1190 fd
= isv6
? v6_sock_fd
: v4_sock_fd
;
1193 * Get the real (64 bit) logical interface flags. Note that the
1194 * routing socket message has flags, but these are just the lower 32
1198 (void) memset(&lifr
, 0, sizeof (lifr
));
1199 (void) strlcpy(lifr
.lifr_name
, lif
->lif_name
, sizeof (lifr
.lifr_name
));
1200 if (ioctl(fd
, SIOCGLIFFLAGS
, &lifr
) == -1) {
1202 * Failing to retrieve flags means that the interface is gone.
1203 * It hasn't failed to verify with DAD, but we still have to
1206 lifr
.lifr_flags
= 0;
1207 if (errno
== ENXIO
) {
1208 lif
->lif_plumbed
= B_FALSE
;
1209 dhcpmsg(MSG_INFO
, "%s has been removed; abandoning",
1212 discard_default_routes(lif
->lif_smachs
);
1215 "unable to retrieve interface flags on %s",
1219 } else if (!check_rtm_addr(ifam
, msglen
, isv6
, &lif
->lif_v6addr
)) {
1221 * If the message is not about this logical interface,
1222 * then just ignore it.
1225 } else if (lifr
.lifr_flags
& IFF_DUPLICATE
) {
1226 dhcpmsg(MSG_ERROR
, "interface %s has duplicate address",
1228 lif_mark_decline(lif
, "duplicate address");
1230 (void) open_ip_lif(lif
, INADDR_ANY
, B_TRUE
);
1233 dad_wait
= lif
->lif_dad_wait
;
1235 dhcpmsg(MSG_VERBOSE
, "check_lif: %s has finished DAD",
1237 lif
->lif_dad_wait
= B_FALSE
;
1247 * check_main_lif(): check the state of a main logical interface for a state
1248 * machine. This is used only for DHCPv6.
1250 * input: dhcp_smach_t *: pointer to the state machine
1251 * const struct ifa_msghdr *: routing socket message
1252 * int: size of routing socket message
1253 * output: boolean_t: B_TRUE if LIF is ok.
1257 check_main_lif(dhcp_smach_t
*dsmp
, const struct ifa_msghdr
*ifam
, int msglen
)
1259 dhcp_lif_t
*lif
= dsmp
->dsm_lif
;
1263 * Get the real (64 bit) logical interface flags. Note that the
1264 * routing socket message has flags, but these are just the lower 32
1267 (void) memset(&lifr
, 0, sizeof (lifr
));
1268 (void) strlcpy(lifr
.lifr_name
, lif
->lif_name
, sizeof (lifr
.lifr_name
));
1269 if (ioctl(v6_sock_fd
, SIOCGLIFFLAGS
, &lifr
) == -1) {
1271 * Failing to retrieve flags means that the interface is gone.
1272 * Our state machine is now trash.
1274 if (errno
== ENXIO
) {
1275 dhcpmsg(MSG_INFO
, "%s has been removed; abandoning",
1279 "unable to retrieve interface flags on %s",
1283 } else if (!check_rtm_addr(ifam
, msglen
, B_TRUE
, &lif
->lif_v6addr
)) {
1285 * If the message is not about this logical interface,
1286 * then just ignore it.
1289 } else if (lifr
.lifr_flags
& IFF_DUPLICATE
) {
1290 dhcpmsg(MSG_ERROR
, "interface %s has duplicate address",
1299 * process_link_up_down(): check the state of a physical interface for up/down
1300 * transitions; must go through INIT_REBOOT state if
1303 * input: dhcp_pif_t *: pointer to the physical interface to check
1304 * const struct if_msghdr *: routing socket message
1309 process_link_up_down(dhcp_pif_t
*pif
, const struct if_msghdr
*ifm
)
1316 * If the message implies no change of flags, then we're done; no need
1317 * to check further. Note that if we have multiple state machines on a
1318 * single physical interface, this test keeps us from issuing an ioctl
1321 if ((ifm
->ifm_flags
& IFF_RUNNING
) && pif
->pif_running
||
1322 !(ifm
->ifm_flags
& IFF_RUNNING
) && !pif
->pif_running
)
1326 * We don't know what the real interface flags are, because the
1327 * if_index number is only 16 bits; we must go ask.
1329 isv6
= pif
->pif_isv6
;
1330 fd
= isv6
? v6_sock_fd
: v4_sock_fd
;
1331 (void) memset(&lifr
, 0, sizeof (lifr
));
1332 (void) strlcpy(lifr
.lifr_name
, pif
->pif_name
, sizeof (lifr
.lifr_name
));
1334 if (ioctl(fd
, SIOCGLIFFLAGS
, &lifr
) == -1 ||
1335 !(lifr
.lifr_flags
& IFF_RUNNING
)) {
1337 * If we've lost the interface or it has gone down, then
1338 * nothing special to do; just turn off the running flag.
1340 pif_status(pif
, B_FALSE
);
1343 * Interface has come back up: go through verification process.
1345 pif_status(pif
, B_TRUE
);
1350 * rtsock_event(): fetches routing socket messages and updates internal
1351 * interface state based on those messages.
1353 * input: iu_eh_t *: unused
1354 * int: the routing socket file descriptor
1355 * (other arguments unused)
1361 rtsock_event(iu_eh_t
*ehp
, int fd
, short events
, iu_event_id_t id
, void *arg
)
1363 dhcp_smach_t
*dsmp
, *dsmnext
;
1365 struct ifa_msghdr ifam
;
1366 struct if_msghdr ifm
;
1373 if ((msglen
= read(fd
, &msg
, sizeof (msg
))) <= 0)
1376 /* Note that the routing socket interface index is just 16 bits */
1377 if (msg
.ifm
.ifm_type
== RTM_IFINFO
) {
1378 ifindex
= msg
.ifm
.ifm_index
;
1379 isv6
= (msg
.ifm
.ifm_flags
& IFF_IPV6
) ? B_TRUE
: B_FALSE
;
1380 } else if (msg
.ifam
.ifam_type
== RTM_DELADDR
||
1381 msg
.ifam
.ifam_type
== RTM_NEWADDR
) {
1382 ifindex
= msg
.ifam
.ifam_index
;
1383 isv6
= is_rtm_v6(&msg
.ifam
, msglen
);
1388 for (dsmp
= lookup_smach_by_uindex(ifindex
, NULL
, isv6
);
1389 dsmp
!= NULL
; dsmp
= dsmnext
) {
1391 boolean_t lif_finished
;
1392 boolean_t lease_removed
;
1393 dhcp_lease_t
*dlp
, *dlnext
;
1396 * Note that script_start can call dhcp_drop directly, and
1397 * that will do release_smach.
1399 dsmnext
= lookup_smach_by_uindex(ifindex
, dsmp
, isv6
);
1400 oldstate
= dsmp
->dsm_state
;
1403 * Ignore state machines that are currently processing drop or
1404 * release; there is nothing more we can do for them.
1406 if (dsmp
->dsm_droprelease
)
1410 * Look for link up/down notifications. These occur on a
1411 * physical interface basis.
1413 if (msg
.ifm
.ifm_type
== RTM_IFINFO
) {
1414 process_link_up_down(dsmp
->dsm_lif
->lif_pif
, &msg
.ifm
);
1419 * Since we cannot trust the flags reported by the routing
1420 * socket (they're just 32 bits -- and thus never include
1421 * IFF_DUPLICATE), and we can't trust the ifindex (it's only 16
1422 * bits and also doesn't reflect the alias in use), we get
1423 * flags on all matching interfaces, and go by that.
1425 lif_finished
= B_FALSE
;
1426 lease_removed
= B_FALSE
;
1427 for (dlp
= dsmp
->dsm_leases
; dlp
!= NULL
; dlp
= dlnext
) {
1428 dhcp_lif_t
*lif
, *lifnext
;
1429 uint_t nlifs
= dlp
->dl_nlifs
;
1431 dlnext
= dlp
->dl_next
;
1432 for (lif
= dlp
->dl_lifs
; lif
!= NULL
&& nlifs
> 0;
1433 lif
= lifnext
, nlifs
--) {
1434 lifnext
= lif
->lif_next
;
1435 if (check_lif(lif
, &msg
.ifam
, msglen
)) {
1436 dsmp
->dsm_lif_wait
--;
1437 lif_finished
= B_TRUE
;
1440 if (dlp
->dl_nlifs
== 0) {
1442 lease_removed
= B_TRUE
;
1446 if ((isv6
&& !check_main_lif(dsmp
, &msg
.ifam
, msglen
)) ||
1447 (!isv6
&& !verify_lif(dsmp
->dsm_lif
))) {
1448 finished_smach(dsmp
, DHCP_IPC_E_INVIF
);
1453 * Ignore this state machine if nothing interesting has
1456 if (!lif_finished
&& dsmp
->dsm_lif_down
== 0 &&
1457 (dsmp
->dsm_leases
!= NULL
|| !lease_removed
))
1461 * If we're still waiting for DAD to complete on some of the
1462 * configured LIFs, then don't send a response.
1464 if (dsmp
->dsm_lif_wait
!= 0) {
1465 dhcpmsg(MSG_VERBOSE
, "rtsock_event: %s still has %d "
1466 "LIFs waiting on DAD", dsmp
->dsm_name
,
1467 dsmp
->dsm_lif_wait
);
1472 * If we have some failed LIFs, then handle them now. We'll
1473 * remove them from the list. Any leases that become empty are
1474 * also removed as part of the decline-generation process.
1476 if (dsmp
->dsm_lif_down
!= 0)
1477 send_declines(dsmp
);
1479 if (dsmp
->dsm_leases
== NULL
) {
1480 dsmp
->dsm_bad_offers
++;
1482 * For DHCPv6, we'll process the restart once we're
1483 * done sending Decline messages, because these are
1484 * supposed to be acknowledged. With DHCPv4, there's
1485 * no acknowledgment for a DECLINE, so after sending
1486 * it, we just restart right away.
1488 if (!dsmp
->dsm_isv6
) {
1489 dhcpmsg(MSG_VERBOSE
, "rtsock_event: %s has no "
1490 "LIFs left", dsmp
->dsm_name
);
1495 * If we're now up on at least some of the leases and
1496 * we were waiting for that, then kick off the rest of
1497 * configuration. Lease validation and DAD are done.
1499 dhcpmsg(MSG_VERBOSE
, "rtsock_event: all LIFs verified "
1500 "on %s in %s state", dsmp
->dsm_name
,
1501 dhcp_state_to_string(oldstate
));
1502 if (oldstate
== PRE_BOUND
||
1503 oldstate
== ADOPTING
)
1504 dhcp_bound_complete(dsmp
);
1505 if (oldstate
== ADOPTING
)
1506 dhcp_adopt_complete(dsmp
);
1512 * check_cmd_allowed(): check whether the requested command is allowed in the
1515 * input: DHCPSTATE: current state
1516 * dhcp_ipc_type_t: requested command
1517 * output: boolean_t: B_TRUE if command is allowed in this state
1521 check_cmd_allowed(DHCPSTATE state
, dhcp_ipc_type_t cmd
)
1523 return (ipc_cmd_allowed
[state
][cmd
] != 0);
1527 is_iscsi_active(void)
1532 if ((fd
= open(ISCSI_DRIVER_DEVCTL
, O_RDONLY
)) != -1) {
1533 if (ioctl(fd
, ISCSI_IS_ACTIVE
, &active
) != 0)
1538 return (active
!= 0);