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]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <arpa/inet.h>
30 #include <libdllink.h>
31 #include <libdlwlan.h>
33 #include <netinet/in.h>
38 #include <sys/socket.h>
39 #include <sys/types.h>
42 #include "conditions.h"
48 * enm.c - contains routines which handle ENM (external network modifier)
49 * abstraction. ENMs represent scripts or services that can be activated either
50 * manually or in response to network conditions.
53 #define CTRUN "/usr/bin/ctrun"
56 enm_create_init_fini_event(nwam_enm_handle_t enmh
, void *data
)
58 boolean_t
*init
= data
;
60 nwamd_event_t enm_event
;
62 if (nwam_enm_get_name(enmh
, &name
) != NWAM_SUCCESS
) {
63 nlog(LOG_ERR
, "enm_init_fini: could not get enm name");
67 enm_event
= nwamd_event_init(*init
?
68 NWAM_EVENT_TYPE_OBJECT_INIT
: NWAM_EVENT_TYPE_OBJECT_FINI
,
69 NWAM_OBJECT_TYPE_ENM
, 0, name
);
70 if (enm_event
!= NULL
)
71 nwamd_event_enqueue(enm_event
);
78 * Walk all ENMs, creating init events for each.
83 boolean_t init
= B_TRUE
;
85 (void) nwam_walk_enms(enm_create_init_fini_event
, &init
, 0, NULL
);
89 * Walk all ENMs, creating fini events for each.
94 boolean_t init
= B_FALSE
;
96 (void) nwam_walk_enms(enm_create_init_fini_event
, &init
, 0, NULL
);
100 enm_is_enabled(nwam_enm_handle_t enmh
)
102 nwam_value_t enabledval
;
103 boolean_t enabled
= B_FALSE
;
105 if (nwam_enm_get_prop_value(enmh
, NWAM_ENM_PROP_ENABLED
,
106 &enabledval
) != NWAM_SUCCESS
) {
107 /* It's legal for a conditional ENM to not specify "enabled" */
110 if (nwam_value_get_boolean(enabledval
, &enabled
) != NWAM_SUCCESS
) {
111 nlog(LOG_ERR
, "enm_is_enabled: could not retrieve "
114 nwam_value_free(enabledval
);
119 enm_get_activation_mode(nwam_enm_handle_t enmh
)
123 nwam_value_t activationval
;
125 if (nwam_enm_get_prop_value(enmh
, NWAM_ENM_PROP_ACTIVATION_MODE
,
126 &activationval
) != NWAM_SUCCESS
) {
127 nlog(LOG_ERR
, "enm_get_activation_mode: could not retrieve "
128 "activation mode value");
131 if (nwam_value_get_uint64(activationval
, &activation
) != NWAM_SUCCESS
) {
132 nlog(LOG_ERR
, "enm_get_activation_mode: could not retrieve "
133 "activation mode value");
138 nwam_value_free(activationval
);
144 nwamd_enm_activate_deactivate_thread(void *arg
)
146 char *object_name
= arg
;
147 nwamd_object_t object
;
148 nwam_enm_handle_t enmh
;
149 nwam_value_t scriptval
= NULL
;
151 nwam_aux_state_t aux_state
;
152 char *script
, *copy
= NULL
;
153 const char **argv
= NULL
;
154 boolean_t going_online
, disable_succeeded
= B_FALSE
;
157 object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
, object_name
);
158 if (object
== NULL
) {
159 nlog(LOG_ERR
, "nwamd_enm_activate_deactivate_thread: "
160 "could not find enm %s", object_name
);
163 enmh
= object
->nwamd_object_handle
;
166 (object
->nwamd_object_state
== NWAM_STATE_OFFLINE_TO_ONLINE
);
168 * We're starting if current state is offline* and stopping otherwise.
170 if (nwam_enm_get_prop_value(enmh
,
171 going_online
? NWAM_ENM_PROP_START
: NWAM_ENM_PROP_STOP
,
172 &scriptval
) != NWAM_SUCCESS
||
173 nwam_value_get_string(scriptval
, &script
) != NWAM_SUCCESS
) {
175 * If we're stopping, it's not an error for no script to
178 nlog(going_online
? LOG_ERR
: LOG_DEBUG
,
179 "nwamd_enm_activate_deactivate_thread: "
180 "no script specified for enm %s", object_name
);
182 state
= NWAM_STATE_MAINTENANCE
;
183 aux_state
= NWAM_AUX_STATE_METHOD_MISSING
;
185 disable_succeeded
= B_TRUE
;
189 const char **newargv
;
193 nlog(LOG_DEBUG
, "nwamd_enm_activate_deactivate_thread: "
194 "running script %s for enm %s", script
, object_name
);
197 * The script may take a number of arguments. We need to
198 * create a string array consisting of the wrapper command
199 * (ctrun), ENM script name, arguments and NULL array
200 * terminator. Start with an array of size equal to the
201 * string length (since the number of arguments will always
202 * be less than this) and shrink array to the actual number
203 * of arguments when we have parsed the string.
205 if ((copy
= strdup(script
)) == NULL
||
206 (argv
= calloc(strlen(script
), sizeof (char *))) == NULL
) {
211 argv
[i
++] = strtok_r(copy
, " ", &lasts
);
212 if (argv
[1] == NULL
) {
217 for (; (argv
[i
] = strtok_r(NULL
, " ", &lasts
)) != NULL
; i
++) {}
219 newargv
= realloc(argv
, (i
+ 1) * sizeof (char *));
222 /* Store the current time as the time the script began */
223 (void) gettimeofday(&now
, NULL
);
224 object
->nwamd_script_time
= now
;
227 * Release the object so that it is not blocked while the
230 nwamd_object_release(object
);
232 ret
= nwamd_start_childv(CTRUN
, argv
);
235 * Find the object again, now that the script has finished
236 * running. Check if this ENM was re-read during that time by
237 * comparing the object's script time with the one from above.
239 object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
, object_name
);
240 if (object
== NULL
) {
241 nlog(LOG_ERR
, "nwamd_enm_activate_deactivate_thread: "
242 "could not find enm %s after running script",
247 if (object
->nwamd_script_time
.tv_sec
!= now
.tv_sec
||
248 object
->nwamd_script_time
.tv_usec
!= now
.tv_usec
) {
249 nlog(LOG_INFO
, "nwamd_enm_activate_deactivate_thread: "
250 "enm %s has been refreshed, nothing to do",
252 nwamd_object_release(object
);
255 (void) gettimeofday(&object
->nwamd_script_time
, NULL
);
259 * If script execution fails and we're not destroying the
260 * object, go to maintenance.
263 nlog(LOG_ERR
, "nwamd_enm_activate_deactivate_thread: "
264 "execution of '%s' failed for enm %s",
265 script
, object_name
);
266 if (object
->nwamd_object_aux_state
!=
267 NWAM_AUX_STATE_UNINITIALIZED
) {
268 state
= NWAM_STATE_MAINTENANCE
;
269 aux_state
= NWAM_AUX_STATE_METHOD_FAILED
;
271 state
= NWAM_STATE_UNINITIALIZED
;
272 aux_state
= NWAM_AUX_STATE_UNINITIALIZED
;
276 state
= NWAM_STATE_ONLINE
;
277 aux_state
= NWAM_AUX_STATE_ACTIVE
;
279 disable_succeeded
= B_TRUE
;
284 if (disable_succeeded
) {
286 * If aux state is "manual disable", we know
287 * this was a disable request, otherwise it was
288 * _fini request or a condition satisfaction
291 switch (object
->nwamd_object_aux_state
) {
292 case NWAM_AUX_STATE_MANUAL_DISABLE
:
293 state
= NWAM_STATE_DISABLED
;
294 aux_state
= NWAM_AUX_STATE_MANUAL_DISABLE
;
296 case NWAM_AUX_STATE_UNINITIALIZED
:
297 state
= NWAM_STATE_UNINITIALIZED
;
298 aux_state
= NWAM_AUX_STATE_UNINITIALIZED
;
301 state
= NWAM_STATE_OFFLINE
;
302 aux_state
= NWAM_AUX_STATE_CONDITIONS_NOT_MET
;
307 /* If state/aux state are uninitialized/unintialized, destroy the ENM */
308 if (state
== NWAM_STATE_UNINITIALIZED
&&
309 aux_state
== NWAM_AUX_STATE_UNINITIALIZED
) {
310 object
->nwamd_object_state
= state
;
311 object
->nwamd_object_aux_state
= aux_state
;
312 (void) nwamd_object_release_and_destroy_after_preserve(object
);
314 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
315 object
->nwamd_object_name
, state
, aux_state
);
316 (void) nwamd_object_release_after_preserve(object
);
320 /* object_name was malloc() before this thread was created, free() it */
324 nwam_value_free(scriptval
);
329 * Run start/stop method for ENM in a separate thread. The object lock is not
330 * held across threads, so we duplicate the object name for the method
331 * execution thread. Returns true if thread is successfully launched.
334 nwamd_enm_run_method(nwamd_object_t object
)
340 * Launch separate thread to wait for execution of script
341 * to complete. Do not hold object lock across threads.
343 if ((name
= strdup(object
->nwamd_object_name
)) == NULL
) {
344 nlog(LOG_ERR
, "nwamd_enm_run_method: %s: out of memory",
345 object
->nwamd_object_name
);
349 if (pthread_create(&script
, NULL
,
350 nwamd_enm_activate_deactivate_thread
, name
) != 0) {
351 nlog(LOG_ERR
, "nwamd_enm_run_method: could not create "
352 "enm script thread for %s", name
);
356 /* "name" will be freed by the newly-created thread. */
358 /* detach thread so that it doesn't become a zombie */
359 (void) pthread_detach(script
);
365 * Activate the ENM, either in response to an enable event or conditions
369 nwamd_enm_activate(const char *object_name
)
371 nwamd_object_t object
;
372 nwam_value_t fmrival
;
373 char *fmri
, *smf_state
;
375 nwam_enm_handle_t enmh
;
377 nwam_aux_state_t aux_state
;
379 boolean_t ran_method
= B_FALSE
;
381 object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
, object_name
);
382 if (object
== NULL
) {
383 nlog(LOG_ERR
, "nwamd_enm_activate: could not find enm %s",
387 state
= object
->nwamd_object_state
;
388 aux_state
= object
->nwamd_object_aux_state
;
389 enmh
= object
->nwamd_object_handle
;
391 nlog(LOG_DEBUG
, "nwamd_enm_activate: activating enm %s",
392 object
->nwamd_object_name
);
394 err
= nwam_enm_get_prop_value(enmh
, NWAM_ENM_PROP_FMRI
, &fmrival
);
398 if (nwam_value_get_string(fmrival
, &fmri
) != NWAM_SUCCESS
) {
399 nlog(LOG_ERR
, "nwamd_enm_activate: could not retrieve "
400 "fmri string for enm %s",
401 object
->nwamd_object_name
);
402 nwam_value_free(fmrival
);
403 state
= NWAM_STATE_MAINTENANCE
;
404 aux_state
= NWAM_AUX_STATE_INVALID_CONFIG
;
408 if ((smf_state
= smf_get_state(fmri
)) == NULL
) {
409 nlog(LOG_ERR
, "nwamd_enm_activate: invalid fmri %s "
410 "for enm %s", fmri
, object
->nwamd_object_name
);
411 nwam_value_free(fmrival
);
412 state
= NWAM_STATE_MAINTENANCE
;
413 aux_state
= NWAM_AUX_STATE_INVALID_CONFIG
;
417 nlog(LOG_DEBUG
, "nwamd_enm_activate: activating %s for enm %s",
418 fmri
, object
->nwamd_object_name
);
420 if (strcmp(smf_state
, SCF_STATE_STRING_ONLINE
) == 0)
421 ret
= smf_restart_instance(fmri
);
422 else if (strcmp(smf_state
, SCF_STATE_STRING_OFFLINE
) == 0)
423 ret
= smf_restart_instance(fmri
);
424 else if (strcmp(smf_state
, SCF_STATE_STRING_DISABLED
) == 0)
425 ret
= smf_enable_instance(fmri
, SMF_TEMPORARY
);
427 ret
= smf_restore_instance(fmri
);
430 state
= NWAM_STATE_ONLINE
;
431 aux_state
= NWAM_AUX_STATE_ACTIVE
;
433 nlog(LOG_ERR
, "nwamd_enm_activate: failed to enable "
434 "fmri %s for enm %s", fmri
,
435 object
->nwamd_object_name
);
436 state
= NWAM_STATE_MAINTENANCE
;
437 aux_state
= NWAM_AUX_STATE_METHOD_FAILED
;
440 nwam_value_free(fmrival
);
444 * Must be a method-based ENM with start (and stop) script(s).
446 if (!nwamd_enm_run_method(object
)) {
447 /* Could not launch method execution thread */
448 state
= NWAM_STATE_MAINTENANCE
;
449 aux_state
= NWAM_AUX_STATE_METHOD_FAILED
;
456 if (state
!= object
->nwamd_object_state
||
457 aux_state
!= object
->nwamd_object_aux_state
) {
458 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
459 object
->nwamd_object_name
, state
, aux_state
);
463 * If the method thread was created, we drop the lock to the ENM
464 * object without decreasing the reference count, ensuring it will not
465 * be destroyed until method execution has completed.
468 nwamd_object_release_and_preserve(object
);
470 nwamd_object_release(object
);
474 /* Deactivates the ENM. */
476 nwamd_enm_deactivate(const char *object_name
)
478 nwamd_object_t object
;
479 nwam_enm_handle_t enmh
;
480 nwam_value_t fmrival
;
481 char *fmri
, *smf_state
;
484 nwam_aux_state_t aux_state
;
485 boolean_t destroying
= B_FALSE
;
487 object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
, object_name
);
488 if (object
== NULL
) {
489 nlog(LOG_ERR
, "nwamd_enm_deactivate: could not find enm %s",
494 state
= object
->nwamd_object_state
;
495 aux_state
= object
->nwamd_object_aux_state
;
496 enmh
= object
->nwamd_object_handle
;
497 state
= object
->nwamd_object_state
;
498 /* If destroying, we don't care about method failure/config err */
499 destroying
= (aux_state
== NWAM_AUX_STATE_UNINITIALIZED
);
501 nlog(LOG_DEBUG
, "nwamd_enm_deactivate: deactivating enm %s",
502 object
->nwamd_object_name
);
504 if (nwam_enm_get_prop_value(enmh
, NWAM_ENM_PROP_FMRI
, &fmrival
)
507 * Must be a method-based ENM with start (and stop) script(s).
508 * Script execution thread will take care of the rest.
509 * If the method thread was created, we drop the lock to the ENM
510 * object without decreasing the reference count, ensuring it
511 * will not be destroyed until method execution has completed.
513 if (nwamd_enm_run_method(object
)) {
514 nwamd_object_release_and_preserve(object
);
517 /* Could not launch method execution thread */
519 state
= NWAM_STATE_MAINTENANCE
;
520 aux_state
= NWAM_AUX_STATE_METHOD_FAILED
;
523 if (nwam_value_get_string(fmrival
, &fmri
) != NWAM_SUCCESS
) {
524 nlog(LOG_ERR
, "nwamd_enm_deactivate: could not "
525 "retrieve fmri string for enm %s",
526 object
->nwamd_object_name
);
528 state
= NWAM_STATE_MAINTENANCE
;
529 aux_state
= NWAM_AUX_STATE_INVALID_CONFIG
;
532 if ((smf_state
= smf_get_state(fmri
)) == NULL
) {
533 nlog(LOG_ERR
, "nwamd_enm_deactivate: invalid "
534 "fmri %s for enm %s", fmri
,
535 object
->nwamd_object_name
);
536 nwam_value_free(fmrival
);
538 state
= NWAM_STATE_MAINTENANCE
;
540 NWAM_AUX_STATE_INVALID_CONFIG
;
546 nlog(LOG_DEBUG
, "nwamd_enm_deactivate: deactivating %s "
547 "for enm %s", fmri
, object
->nwamd_object_name
);
549 ret
= smf_disable_instance(fmri
, SMF_TEMPORARY
);
552 nlog(LOG_ERR
, "nwamd_enm_deactivate: "
553 "smf_disable_instance(%s) failed for "
555 object
->nwamd_object_name
,
556 scf_strerror(scf_error()));
558 state
= NWAM_STATE_MAINTENANCE
;
560 NWAM_AUX_STATE_METHOD_FAILED
;
564 nwam_value_free(fmrival
);
567 if (state
== object
->nwamd_object_state
&&
568 aux_state
== object
->nwamd_object_aux_state
) {
570 * If aux state is "manual disable", we know
571 * this was a disable request, otherwise it was
572 * a _fini request or a condition satisfaction
575 switch (object
->nwamd_object_aux_state
) {
576 case NWAM_AUX_STATE_MANUAL_DISABLE
:
577 state
= NWAM_STATE_DISABLED
;
578 aux_state
= NWAM_AUX_STATE_MANUAL_DISABLE
;
580 case NWAM_AUX_STATE_UNINITIALIZED
:
581 state
= NWAM_STATE_UNINITIALIZED
;
582 aux_state
= NWAM_AUX_STATE_UNINITIALIZED
;
585 state
= NWAM_STATE_OFFLINE
;
586 aux_state
= NWAM_AUX_STATE_CONDITIONS_NOT_MET
;
591 /* Only change state if we aren't destroying the ENM */
592 if (!destroying
&& (state
!= object
->nwamd_object_state
||
593 aux_state
!= object
->nwamd_object_aux_state
)) {
594 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
595 object
->nwamd_object_name
, state
, aux_state
);
598 /* If state/aux state are uninitialized/unintialized, destroy the ENM */
599 if (state
== NWAM_STATE_UNINITIALIZED
&&
600 aux_state
== NWAM_AUX_STATE_UNINITIALIZED
) {
601 (void) nwamd_object_release_and_destroy(object
);
603 (void) nwamd_object_release(object
);
608 * Determine whether an ENM should be (de)activated.
612 nwamd_enm_check(nwamd_object_t object
, void *data
)
614 nwam_enm_handle_t enmh
;
615 nwam_value_t conditionval
;
617 boolean_t enabled
, satisfied
;
622 state
= object
->nwamd_object_state
;
624 enmh
= object
->nwamd_object_handle
;
626 eactivation
= enm_get_activation_mode(enmh
);
627 if (eactivation
== -1)
630 switch (eactivation
) {
631 case NWAM_ACTIVATION_MODE_MANUAL
:
632 enabled
= enm_is_enabled(enmh
);
635 nlog(LOG_DEBUG
, "nwamd_enm_check: %s is enabled",
636 object
->nwamd_object_name
);
638 case NWAM_STATE_ONLINE
:
639 case NWAM_STATE_MAINTENANCE
:
643 if (nwamd_enm_action(object
->nwamd_object_name
,
644 NWAM_ACTION_ENABLE
) != 0) {
645 nlog(LOG_ERR
, "nwamd_enm_check: "
646 "enable failed for enm %s",
647 object
->nwamd_object_name
);
652 nlog(LOG_DEBUG
, "nwamd_enm_check: %s is disabled",
653 object
->nwamd_object_name
);
655 case NWAM_STATE_ONLINE
:
656 if (nwamd_enm_action(object
->nwamd_object_name
,
657 NWAM_ACTION_DISABLE
) != 0) {
658 nlog(LOG_ERR
, "nwamd_enm_check: "
659 "disable failed for enm %s",
660 object
->nwamd_object_name
);
663 case NWAM_STATE_MAINTENANCE
:
666 case NWAM_STATE_DISABLED
:
670 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
671 object
->nwamd_object_name
,
673 NWAM_AUX_STATE_MANUAL_DISABLE
);
679 case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY
:
680 case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL
:
681 if (nwam_enm_get_prop_value(enmh
,
682 NWAM_ENM_PROP_CONDITIONS
, &conditionval
) != NWAM_SUCCESS
) {
683 nlog(LOG_ERR
, "nwamd_enm_check: could not retrieve "
687 if (nwam_value_get_string_array(conditionval
,
688 &conditions
, &nelem
) != NWAM_SUCCESS
) {
689 nlog(LOG_ERR
, "nwamd_enm_check: could not retrieve "
691 nwam_value_free(conditionval
);
694 satisfied
= nwamd_check_conditions((uint64_t)eactivation
,
697 nlog(LOG_DEBUG
, "nwamd_enm_check: conditions for enm %s "
698 "%s satisfied", object
->nwamd_object_name
,
699 satisfied
? "is" : "is not");
700 if (state
!= NWAM_STATE_ONLINE
&& satisfied
) {
701 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
702 object
->nwamd_object_name
,
703 NWAM_STATE_OFFLINE_TO_ONLINE
,
704 NWAM_AUX_STATE_METHOD_RUNNING
);
706 if (state
== NWAM_STATE_ONLINE
&& !satisfied
) {
707 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
708 object
->nwamd_object_name
,
709 NWAM_STATE_ONLINE_TO_OFFLINE
,
710 NWAM_AUX_STATE_CONDITIONS_NOT_MET
);
712 nwam_value_free(conditionval
);
720 nwamd_enm_check_conditions(void)
722 (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_ENM
, nwamd_enm_check
, NULL
);
726 nwamd_enm_action(const char *enm
, nwam_action_t action
)
728 nwamd_event_t event
= nwamd_event_init_object_action
729 (NWAM_OBJECT_TYPE_ENM
, enm
, NULL
, action
);
732 nwamd_event_enqueue(event
);
737 * Event handling functions.
740 /* Handle ENM initialization/refresh event */
742 nwamd_enm_handle_init_event(nwamd_event_t event
)
744 nwamd_object_t object
;
745 nwam_enm_handle_t enmh
;
747 boolean_t manual_disabled
= B_FALSE
;
749 if ((err
= nwam_enm_read(event
->event_object
, 0, &enmh
))
751 nlog(LOG_ERR
, "nwamd_enm_handle_init_event: could not "
752 "read object '%s': %s", event
->event_object
,
754 nwamd_event_do_not_send(event
);
757 if ((object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
,
758 event
->event_object
)) != NULL
) {
759 nwam_enm_free(object
->nwamd_object_handle
);
760 object
->nwamd_object_handle
= enmh
;
762 object
= nwamd_object_init(NWAM_OBJECT_TYPE_ENM
,
763 event
->event_object
, enmh
, NULL
);
764 object
->nwamd_object_state
= NWAM_STATE_OFFLINE
;
765 object
->nwamd_object_aux_state
=
766 NWAM_AUX_STATE_CONDITIONS_NOT_MET
;
768 /* (Re)set script time to now as the object has just been (re)read */
769 (void) gettimeofday(&object
->nwamd_script_time
, NULL
);
771 manual_disabled
= (enm_get_activation_mode(enmh
) ==
772 NWAM_ACTIVATION_MODE_MANUAL
&& !enm_is_enabled(enmh
));
775 * If this ENM is ONLINE, and not manual and disabled (since in
776 * that case it was online but we've just set enabled = false as part
777 * of a disable action), then it is still active but refreshing.
778 * Change states to re-activate itself.
780 if (!manual_disabled
&&
781 object
->nwamd_object_state
== NWAM_STATE_ONLINE
) {
782 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
783 event
->event_object
, NWAM_STATE_OFFLINE_TO_ONLINE
,
784 NWAM_AUX_STATE_METHOD_RUNNING
);
786 nwamd_object_release(object
);
789 /* Handle ENM finish event */
791 nwamd_enm_handle_fini_event(nwamd_event_t event
)
793 nwamd_event_t state_event
;
795 nlog(LOG_DEBUG
, "nwamd_enm_handle_fini_event(%s)", event
->event_object
);
798 * Simulate a state event so that the state machine can correctly
799 * deactivate the ENM and free up the handle.
801 state_event
= nwamd_event_init_object_state(NWAM_OBJECT_TYPE_ENM
,
802 event
->event_object
, NWAM_STATE_ONLINE_TO_OFFLINE
,
803 NWAM_AUX_STATE_UNINITIALIZED
);
804 if (state_event
== NULL
) {
805 nwamd_event_do_not_send(event
);
808 nwamd_enm_handle_state_event(state_event
);
809 nwamd_event_fini(state_event
);
811 * Do not free the handle and object.
812 * nwamd_enm_activate_deactivate_thread() and
813 * nwamd_enm_deactivate() does this after running the stop script
814 * and disabling the FMRI respectively.
819 nwamd_enm_handle_action_event(nwamd_event_t event
)
821 nwamd_object_t object
;
823 switch (event
->event_msg
->nwe_data
.nwe_object_action
.nwe_action
) {
824 case NWAM_ACTION_ENABLE
:
825 object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
,
826 event
->event_object
);
827 if (object
== NULL
) {
828 nlog(LOG_ERR
, "nwamd_enm_handle_action_event: "
829 "could not find enm %s", event
->event_object
);
830 nwamd_event_do_not_send(event
);
833 if (object
->nwamd_object_state
== NWAM_STATE_ONLINE
) {
834 nlog(LOG_DEBUG
, "nwamd_enm_handle_action_event: "
835 "enm %s already online, nothing to do",
836 event
->event_object
);
837 nwamd_object_release(object
);
840 nwamd_object_release(object
);
842 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
843 event
->event_object
, NWAM_STATE_OFFLINE_TO_ONLINE
,
844 NWAM_AUX_STATE_METHOD_RUNNING
);
846 case NWAM_ACTION_DISABLE
:
847 object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
,
848 event
->event_object
);
849 if (object
== NULL
) {
850 nlog(LOG_ERR
, "nwamd_enm_handle_action_event: "
851 "could not find enm %s", event
->event_object
);
852 nwamd_event_do_not_send(event
);
855 if (object
->nwamd_object_state
== NWAM_STATE_DISABLED
) {
856 nlog(LOG_DEBUG
, "nwamd_enm_handle_action_event: "
857 "enm %s already disabled, nothing to do",
858 event
->event_object
);
859 nwamd_object_release(object
);
862 nwamd_object_release(object
);
864 nwamd_object_set_state(NWAM_OBJECT_TYPE_ENM
,
865 event
->event_object
, NWAM_STATE_ONLINE_TO_OFFLINE
,
866 NWAM_AUX_STATE_MANUAL_DISABLE
);
868 case NWAM_ACTION_ADD
:
869 case NWAM_ACTION_REFRESH
:
870 nwamd_enm_handle_init_event(event
);
872 case NWAM_ACTION_DESTROY
:
873 nwamd_enm_handle_fini_event(event
);
876 nlog(LOG_INFO
, "nwam_enm_handle_action_event: "
877 "unexpected action");
878 nwamd_event_do_not_send(event
);
884 nwamd_enm_handle_state_event(nwamd_event_t event
)
886 nwamd_object_t object
;
887 nwam_state_t new_state
;
888 nwam_aux_state_t new_aux_state
;
890 if ((object
= nwamd_object_find(NWAM_OBJECT_TYPE_ENM
,
891 event
->event_object
)) == NULL
) {
892 nlog(LOG_INFO
, "nwamd_enm_handle_state_event: "
893 "state event for nonexistent enm %s", event
->event_object
);
894 nwamd_event_do_not_send(event
);
897 new_state
= event
->event_msg
->nwe_data
.nwe_object_state
.nwe_state
;
899 event
->event_msg
->nwe_data
.nwe_object_state
.nwe_aux_state
;
901 if (new_state
== object
->nwamd_object_state
&&
902 new_aux_state
== object
->nwamd_object_aux_state
) {
903 nlog(LOG_DEBUG
, "nwamd_enm_handle_state_event: "
904 "enm %s already in state (%s , %s)",
905 object
->nwamd_object_name
, nwam_state_to_string(new_state
),
906 nwam_aux_state_to_string(new_aux_state
));
907 nwamd_object_release(object
);
911 object
->nwamd_object_state
= new_state
;
912 object
->nwamd_object_aux_state
= new_aux_state
;
914 nlog(LOG_DEBUG
, "nwamd_enm_handle_state_event: changing state for enm "
915 "%s to (%s , %s)", object
->nwamd_object_name
,
916 nwam_state_to_string(object
->nwamd_object_state
),
917 nwam_aux_state_to_string(object
->nwamd_object_aux_state
));
919 nwamd_object_release(object
);
922 * State machine for ENMs.
925 case NWAM_STATE_OFFLINE_TO_ONLINE
:
926 nwamd_enm_activate(event
->event_object
);
928 case NWAM_STATE_ONLINE_TO_OFFLINE
:
929 nwamd_enm_deactivate(event
->event_object
);
931 case NWAM_STATE_DISABLED
:
932 case NWAM_STATE_OFFLINE
:
933 case NWAM_STATE_UNINITIALIZED
:
934 case NWAM_STATE_MAINTENANCE
:
935 case NWAM_STATE_DEGRADED
: