xref: /illumos-gate/usr/src/lib/libnwam/common/libnwam_enm.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <assert.h>
28 #include <ctype.h>
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <strings.h>
35 #include <unistd.h>
36 #include <libscf.h>
37 #include "libnwam_impl.h"
38 #include <libnwam_priv.h>
39 #include <libnwam.h>
40 
41 /*
42  * Functions to support creating, modifying, destroying, querying the
43  * state of and changing the state of ENM (External Network Modifier)
44  * objects.  ENMs represent services or scripts that can be enabled
45  * either manually or conditionally for a combination of the set of
46  * available conditions (an IP address is present, a location is active etc).
47  */
48 
49 typedef nwam_error_t (*nwam_enm_prop_validate_func_t)(nwam_value_t);
50 
51 static nwam_error_t valid_enm_activation_mode(nwam_value_t);
52 
53 struct nwam_prop_table_entry enm_prop_table_entries[] = {
54 	{NWAM_ENM_PROP_ACTIVATION_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
55 	    valid_enm_activation_mode,
56 	    "specifies the ENM activation mode - valid values are:\n"
57 	    "\'manual\', \'conditional-any\' and \'conditional-all\'",
58 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
59 	{NWAM_ENM_PROP_CONDITIONS, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
60 	    NWAM_MAX_NUM_VALUES, nwam_valid_condition,
61 	    "specifies the activation condition. Conditions are of the form:\n"
62 	    "ncp|ncu|enm|loc name is|is-not active\n"
63 	    "ip-address is|is-not|is-in-range|is-not-in-range| 1.2.3.4[/24]\n"
64 	    "advertised-domain is|is-not|contains|does-not-contain string\n"
65 	    "system-domain is|is-not|contains|does-not-contain string\n"
66 	    "essid is|is-not|contains|does-not-contain string\n"
67 	    "bssid is|is-not string",
68 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
69 	{NWAM_ENM_PROP_ENABLED, NWAM_VALUE_TYPE_BOOLEAN, B_TRUE, 0, 1,
70 	    nwam_valid_boolean,
71 	    "specifies if manual ENM is to be enabled",
72 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
73 	{NWAM_ENM_PROP_FMRI, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
74 	    nwam_valid_fmri,
75 	    "specifies SMF FMRI of service to be enabled on ENM activation",
76 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
77 	{NWAM_ENM_PROP_START, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
78 	    nwam_valid_file,
79 	    "specifies absolute path to start script to be run on ENM "
80 	    "activation",
81 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY},
82 	{NWAM_ENM_PROP_STOP, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
83 	    nwam_valid_file,
84 	    "specifies absolute path to stop script to be run on ENM "
85 	    "deactivation",
86 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY}
87 };
88 
89 #define	NWAM_NUM_ENM_PROPS	(sizeof (enm_prop_table_entries) / \
90 				sizeof (*enm_prop_table_entries))
91 
92 struct nwam_prop_table enm_prop_table =
93 	{ NWAM_NUM_ENM_PROPS, enm_prop_table_entries };
94 
95 static uint64_t
96 nwam_enm_activation_to_flag(nwam_activation_mode_t activation)
97 {
98 	switch (activation) {
99 	case NWAM_ACTIVATION_MODE_MANUAL:
100 		return (NWAM_FLAG_ACTIVATION_MODE_MANUAL);
101 	case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY:
102 		return (NWAM_FLAG_ACTIVATION_MODE_CONDITIONAL_ANY);
103 	case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL:
104 		return (NWAM_FLAG_ACTIVATION_MODE_CONDITIONAL_ALL);
105 	default:
106 		return (0);
107 	}
108 }
109 
110 nwam_error_t
111 nwam_enm_read(const char *name, uint64_t flags, nwam_enm_handle_t *enmhp)
112 {
113 	return (nwam_read(NWAM_OBJECT_TYPE_ENM, NWAM_ENM_CONF_FILE, name,
114 	    flags, enmhp));
115 }
116 
117 nwam_error_t
118 nwam_enm_create(const char *name, const char *fmri, nwam_enm_handle_t *enmhp)
119 {
120 	nwam_error_t err;
121 	nwam_value_t actval = NULL, falseval = NULL, fmrival = NULL;
122 
123 	assert(enmhp != NULL && name != NULL);
124 
125 	if ((err = nwam_create(NWAM_OBJECT_TYPE_ENM, NWAM_ENM_CONF_FILE, name,
126 	    enmhp)) != NWAM_SUCCESS)
127 		return (err);
128 
129 	/*
130 	 * Create new object list for ENM.  The initial activation mode is set,
131 	 * and the FMRI property is set, if specified.
132 	 */
133 	if ((err = nwam_alloc_object_list(&((*enmhp)->nwh_data)))
134 	    != NWAM_SUCCESS)
135 		goto finish;
136 
137 	if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL,
138 	    &actval)) != NWAM_SUCCESS ||
139 	    ((fmri != NULL) &&
140 	    (err = nwam_value_create_string((char *)fmri, &fmrival))
141 	    != NWAM_SUCCESS) ||
142 	    (err = nwam_value_create_boolean(B_FALSE, &falseval))
143 	    != NWAM_SUCCESS) {
144 		goto finish;
145 	}
146 	if ((err = nwam_set_prop_value((*enmhp)->nwh_data,
147 	    NWAM_ENM_PROP_ACTIVATION_MODE, actval)) == NWAM_SUCCESS &&
148 	    (err = nwam_set_prop_value((*enmhp)->nwh_data,
149 	    NWAM_ENM_PROP_ENABLED, falseval)) == NWAM_SUCCESS) {
150 		if (fmri != NULL) {
151 			err = nwam_set_prop_value((*enmhp)->nwh_data,
152 			    NWAM_ENM_PROP_FMRI, fmrival);
153 		}
154 	}
155 
156 finish:
157 	nwam_value_free(actval);
158 	nwam_value_free(falseval);
159 	if (fmrival != NULL)
160 		nwam_value_free(fmrival);
161 
162 	if (err != NWAM_SUCCESS) {
163 		nwam_enm_free(*enmhp);
164 		*enmhp = NULL;
165 	}
166 
167 	return (err);
168 }
169 
170 nwam_error_t
171 nwam_enm_get_name(nwam_enm_handle_t enmh, char **namep)
172 {
173 	return (nwam_get_name(enmh, namep));
174 }
175 
176 nwam_error_t
177 nwam_enm_set_name(nwam_enm_handle_t enmh, const char *name)
178 {
179 	return (nwam_set_name(enmh, name));
180 }
181 
182 boolean_t
183 nwam_enm_can_set_name(nwam_enm_handle_t enmh)
184 {
185 	return (!enmh->nwh_committed);
186 }
187 
188 /* ARGSUSED2 */
189 static int
190 enm_selectcb(struct nwam_handle *hp, uint64_t flags, void *data)
191 {
192 	nwam_enm_handle_t enmh = hp;
193 	uint64_t activation, actflag, walkfilter;
194 	nwam_value_t actval;
195 
196 	/*
197 	 * Get a bitmapped flag value corresponding to this enm's
198 	 * activation value - if the activation value is not recognized,
199 	 * actflag will be set to 0, and will thus fail to match
200 	 * any bit flag passed in by the caller.
201 	 */
202 	if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ACTIVATION_MODE,
203 	    &actval) != NWAM_SUCCESS) {
204 		return (NWAM_INVALID_ARG);
205 	}
206 	if (nwam_value_get_uint64(actval, &activation) != NWAM_SUCCESS) {
207 		nwam_value_free(actval);
208 		return (NWAM_INVALID_ARG);
209 	}
210 
211 	actflag = nwam_enm_activation_to_flag(activation);
212 	nwam_value_free(actval);
213 	if ((walkfilter = flags & NWAM_WALK_FILTER_MASK) == 0)
214 		walkfilter = NWAM_FLAG_ACTIVATION_MODE_ALL;
215 	if (actflag & walkfilter)
216 		return (NWAM_SUCCESS);
217 	return (NWAM_INVALID_ARG);
218 }
219 
220 nwam_error_t
221 nwam_walk_enms(int(*cb)(nwam_enm_handle_t, void *), void *data, uint64_t flags,
222     int *retp)
223 {
224 	nwam_error_t err = nwam_valid_flags(flags,
225 	    NWAM_FLAG_ACTIVATION_MODE_ALL | NWAM_FLAG_BLOCKING);
226 
227 	if (err != NWAM_SUCCESS)
228 		return (err);
229 
230 	return (nwam_walk(NWAM_OBJECT_TYPE_ENM, NWAM_ENM_CONF_FILE,
231 	    cb, data, flags, retp, enm_selectcb));
232 }
233 
234 void
235 nwam_enm_free(nwam_enm_handle_t enmh)
236 {
237 	nwam_free(enmh);
238 }
239 
240 nwam_error_t
241 nwam_enm_copy(nwam_enm_handle_t oldenmh, const char *newname,
242     nwam_enm_handle_t *newenmhp)
243 {
244 	return (nwam_copy(NWAM_ENM_CONF_FILE, oldenmh, newname, newenmhp));
245 }
246 
247 nwam_error_t
248 nwam_enm_delete_prop(nwam_enm_handle_t enmh, const char *propname)
249 {
250 	nwam_error_t err;
251 	boolean_t ro;
252 	void *olddata;
253 	boolean_t manual;
254 
255 	assert(enmh != NULL && propname != NULL);
256 
257 	if ((err = nwam_enm_prop_read_only(propname, &ro)) != NWAM_SUCCESS)
258 		return (err);
259 	if (ro) {
260 		/*
261 		 * If the activation-mode is not manual, allow the enabled
262 		 * property to be deleted.
263 		 */
264 		if (strcmp(propname, NWAM_ENM_PROP_ENABLED) != 0)
265 			return (NWAM_ENTITY_READ_ONLY);
266 
267 		if ((err = nwam_enm_is_manual(enmh, &manual)) != NWAM_SUCCESS)
268 			return (err);
269 		if (manual)
270 			return (NWAM_ENTITY_READ_ONLY);
271 	}
272 
273 	/*
274 	 * Duplicate data, remove property and validate. If validation
275 	 * fails, revert to data duplicated prior to remove.
276 	 */
277 	if ((err = nwam_dup_object_list(enmh->nwh_data, &olddata))
278 	    != NWAM_SUCCESS)
279 		return (err);
280 	if ((err = nwam_delete_prop(enmh->nwh_data, propname))
281 	    != NWAM_SUCCESS) {
282 		nwam_free_object_list(enmh->nwh_data);
283 		enmh->nwh_data = olddata;
284 		return (err);
285 	}
286 	if ((err = nwam_enm_validate(enmh, NULL)) != NWAM_SUCCESS) {
287 		nwam_free_object_list(enmh->nwh_data);
288 		enmh->nwh_data = olddata;
289 		return (err);
290 	}
291 	nwam_free_object_list(olddata);
292 
293 	return (NWAM_SUCCESS);
294 }
295 
296 nwam_error_t
297 nwam_enm_set_prop_value(nwam_enm_handle_t enmh, const char *propname,
298     nwam_value_t value)
299 {
300 	nwam_error_t err;
301 	boolean_t ro;
302 
303 	assert(enmh != NULL && propname != NULL && value != NULL);
304 
305 	if ((err = nwam_enm_validate_prop(enmh, propname, value))
306 	    != NWAM_SUCCESS ||
307 	    (err = nwam_enm_prop_read_only(propname, &ro)) != NWAM_SUCCESS)
308 		return (err);
309 	if (ro)
310 		return (NWAM_ENTITY_READ_ONLY);
311 
312 	return (nwam_set_prop_value(enmh->nwh_data, propname, value));
313 }
314 
315 nwam_error_t
316 nwam_enm_get_prop_value(nwam_enm_handle_t enmh, const char *propname,
317     nwam_value_t *valuep)
318 {
319 	return (nwam_get_prop_value(enmh->nwh_data, propname, valuep));
320 }
321 
322 nwam_error_t
323 nwam_enm_walk_props(nwam_enm_handle_t enmh,
324     int (*cb)(const char *, nwam_value_t, void *),
325     void *data, uint64_t flags, int *retp)
326 {
327 	return (nwam_walk_props(enmh, cb, data, flags, retp));
328 }
329 
330 nwam_error_t
331 nwam_enm_commit(nwam_enm_handle_t enmh, uint64_t flags)
332 {
333 	nwam_error_t err;
334 
335 	assert(enmh != NULL && enmh->nwh_data != NULL);
336 
337 	if ((err = nwam_enm_validate(enmh, NULL)) != NWAM_SUCCESS)
338 		return (err);
339 
340 	return (nwam_commit(NWAM_ENM_CONF_FILE, enmh, flags));
341 }
342 
343 nwam_error_t
344 nwam_enm_destroy(nwam_enm_handle_t enmh, uint64_t flags)
345 {
346 	return (nwam_destroy(NWAM_ENM_CONF_FILE, enmh, flags));
347 }
348 
349 nwam_error_t
350 nwam_enm_get_prop_description(const char *propname, const char **descriptionp)
351 {
352 	return (nwam_get_prop_description(enm_prop_table, propname,
353 	    descriptionp));
354 }
355 
356 nwam_error_t
357 nwam_enm_prop_read_only(const char *propname, boolean_t *readp)
358 {
359 	return (nwam_prop_read_only(enm_prop_table, propname, readp));
360 }
361 
362 /* Property-specific value validation functions follow */
363 
364 static nwam_error_t
365 valid_enm_activation_mode(nwam_value_t value)
366 {
367 	uint64_t activation_mode;
368 
369 	if (nwam_value_get_uint64(value, &activation_mode) != NWAM_SUCCESS)
370 		return (NWAM_ENTITY_INVALID_VALUE);
371 
372 	switch (activation_mode) {
373 	case NWAM_ACTIVATION_MODE_MANUAL:
374 	case NWAM_ACTIVATION_MODE_CONDITIONAL_ANY:
375 	case NWAM_ACTIVATION_MODE_CONDITIONAL_ALL:
376 		return (NWAM_SUCCESS);
377 	}
378 	return (NWAM_ENTITY_INVALID_VALUE);
379 }
380 
381 nwam_error_t
382 nwam_enm_validate(nwam_enm_handle_t enmh, const char **errpropp)
383 {
384 	uint64_t activation;
385 	nwam_value_t activationval, enabledval, fmrival = NULL, startval = NULL;
386 	nwam_value_t conditionval = NULL;
387 	char **conditions, *name;
388 	uint_t i, numvalues;
389 	nwam_condition_object_type_t object_type;
390 	nwam_condition_t condition;
391 
392 	assert(enmh != NULL);
393 
394 	/*
395 	 * Make sure enm is internally consistent: must have either
396 	 * an fmri or a start string; and if activation type is conditional,
397 	 * the condition string must be specified.
398 	 */
399 	if ((nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_FMRI, &fmrival)
400 	    != NWAM_SUCCESS) &&
401 	    (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_START, &startval)
402 	    != NWAM_SUCCESS)) {
403 		if (fmrival != NULL) {
404 			if (errpropp != NULL)
405 				*errpropp = NWAM_ENM_PROP_START;
406 			nwam_value_free(fmrival);
407 		} else {
408 			if (errpropp != NULL)
409 				*errpropp = NWAM_ENM_PROP_FMRI;
410 		}
411 		return (NWAM_ENTITY_MISSING_MEMBER);
412 	}
413 	if (fmrival != NULL)
414 		nwam_value_free(fmrival);
415 	if (startval != NULL)
416 		nwam_value_free(startval);
417 
418 	if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ACTIVATION_MODE,
419 	    &activationval) != NWAM_SUCCESS) {
420 		if (errpropp != NULL)
421 			*errpropp = NWAM_ENM_PROP_ACTIVATION_MODE;
422 		return (NWAM_ENTITY_MISSING_MEMBER);
423 	}
424 	if (nwam_value_get_uint64(activationval, &activation)
425 	    != NWAM_SUCCESS) {
426 		if (errpropp != NULL)
427 			*errpropp = NWAM_ENM_PROP_ACTIVATION_MODE;
428 		return (NWAM_ENTITY_INVALID_VALUE);
429 	}
430 	nwam_value_free(activationval);
431 
432 	if (activation == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY ||
433 	    activation == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL) {
434 		if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_CONDITIONS,
435 		    &conditionval) != NWAM_SUCCESS) {
436 			if (errpropp != NULL)
437 				*errpropp = NWAM_ENM_PROP_CONDITIONS;
438 			return (NWAM_ENTITY_MISSING_MEMBER);
439 		}
440 		/*
441 		 * Are conditions self-referential? In other words, do any
442 		 * of the activation conditions refer to this ENM?
443 		 */
444 		if (nwam_value_get_string_array(conditionval, &conditions,
445 		    &numvalues) != NWAM_SUCCESS) {
446 			nwam_value_free(conditionval);
447 			if (errpropp != NULL)
448 				*errpropp = NWAM_ENM_PROP_CONDITIONS;
449 			return (NWAM_ENTITY_INVALID_VALUE);
450 		}
451 		if (nwam_enm_get_name(enmh, &name) != NWAM_SUCCESS) {
452 			nwam_value_free(conditionval);
453 			return (NWAM_INVALID_ARG);
454 		}
455 		for (i = 0; i < numvalues; i++) {
456 			char *object_name = NULL;
457 
458 			if (nwam_condition_string_to_condition(conditions[i],
459 			    &object_type, &condition, &object_name)
460 			    != NWAM_SUCCESS) {
461 				if (errpropp != NULL)
462 					*errpropp = NWAM_ENM_PROP_CONDITIONS;
463 				free(name);
464 				nwam_value_free(conditionval);
465 				return (NWAM_ENTITY_INVALID_VALUE);
466 			}
467 			if (object_name != NULL &&
468 			    object_type == NWAM_CONDITION_OBJECT_TYPE_ENM &&
469 			    strcmp(object_name, name) == 0) {
470 				if (errpropp != NULL)
471 					*errpropp = NWAM_ENM_PROP_CONDITIONS;
472 				free(name);
473 				free(object_name);
474 				nwam_value_free(conditionval);
475 				return (NWAM_ENTITY_INVALID_VALUE);
476 			}
477 			free(object_name);
478 		}
479 		free(name);
480 		nwam_value_free(conditionval);
481 	}
482 
483 	if (activation == NWAM_ACTIVATION_MODE_MANUAL) {
484 		if (nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ENABLED,
485 		    &enabledval) != NWAM_SUCCESS) {
486 			if (errpropp != NULL)
487 				*errpropp = NWAM_ENM_PROP_ENABLED;
488 			return (NWAM_ENTITY_MISSING_MEMBER);
489 		}
490 		nwam_value_free(enabledval);
491 	}
492 
493 	return (nwam_validate(enm_prop_table, enmh, errpropp));
494 }
495 
496 nwam_error_t
497 nwam_enm_validate_prop(nwam_enm_handle_t enmh, const char *propname,
498     nwam_value_t value)
499 {
500 	assert(enmh != NULL);
501 
502 	return (nwam_validate_prop(enm_prop_table, enmh, propname, value));
503 }
504 
505 /*
506  * Given a property, return expected property data type
507  */
508 nwam_error_t
509 nwam_enm_get_prop_type(const char *propname, nwam_value_type_t *typep)
510 {
511 	return (nwam_get_prop_type(enm_prop_table, propname, typep));
512 }
513 
514 nwam_error_t
515 nwam_enm_prop_multivalued(const char *propname, boolean_t *multip)
516 {
517 	return (nwam_prop_multivalued(enm_prop_table, propname, multip));
518 }
519 
520 /*
521  * Determine if the ENM has manual activation-mode or not.
522  */
523 nwam_error_t
524 nwam_enm_is_manual(nwam_enm_handle_t enmh, boolean_t *manualp)
525 {
526 	nwam_error_t err;
527 	nwam_value_t actval;
528 	uint64_t activation;
529 
530 	assert(enmh != NULL);
531 
532 	if ((err = nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ACTIVATION_MODE,
533 	    &actval)) != NWAM_SUCCESS)
534 		return (err);
535 	err = nwam_value_get_uint64(actval, &activation);
536 	nwam_value_free(actval);
537 	if (err != NWAM_SUCCESS)
538 		return (err);
539 
540 	if (activation == NWAM_ACTIVATION_MODE_MANUAL)
541 		*manualp = B_TRUE;
542 	else
543 		*manualp = B_FALSE;
544 	return (NWAM_SUCCESS);
545 }
546 
547 /* Determine if ENM is enabled or not */
548 static nwam_error_t
549 nwam_enm_is_enabled(nwam_enm_handle_t enmh, boolean_t *enabledp)
550 {
551 	nwam_error_t err;
552 	nwam_value_t enabledval;
553 
554 	assert(enmh != NULL);
555 
556 	if ((err = nwam_enm_get_prop_value(enmh, NWAM_ENM_PROP_ENABLED,
557 	    &enabledval)) != NWAM_SUCCESS)
558 		return (err);
559 	err = nwam_value_get_boolean(enabledval, enabledp);
560 	nwam_value_free(enabledval);
561 	return (err);
562 }
563 
564 /* Update the enabled property */
565 static nwam_error_t
566 nwam_enm_update_enabled(nwam_enm_handle_t enmh, boolean_t enabled)
567 {
568 	nwam_error_t err;
569 	nwam_value_t enabledval;
570 
571 	if ((err = nwam_value_create_boolean(enabled, &enabledval))
572 	    != NWAM_SUCCESS)
573 		return (err);
574 	err = nwam_set_prop_value(enmh->nwh_data, NWAM_ENM_PROP_ENABLED,
575 	    enabledval);
576 	nwam_value_free(enabledval);
577 	if (err != NWAM_SUCCESS)
578 		return (err);
579 	return (nwam_enm_commit(enmh, NWAM_FLAG_ENTITY_ENABLE));
580 }
581 
582 nwam_error_t
583 nwam_enm_enable(nwam_enm_handle_t enmh)
584 {
585 	nwam_error_t err;
586 	boolean_t manual, enabled;
587 
588 	assert(enmh != NULL);
589 
590 	/* Only enms with manual activation-mode can be enabled */
591 	if ((err = nwam_enm_is_manual(enmh, &manual)) != NWAM_SUCCESS)
592 		return (err);
593 	if (!manual)
594 		return (NWAM_ENTITY_NOT_MANUAL);
595 
596 	/* Make sure ENM is not enabled */
597 	if ((err = nwam_enm_is_enabled(enmh, &enabled)) != NWAM_SUCCESS)
598 		return (err);
599 	if (enabled)
600 		return (NWAM_SUCCESS);
601 
602 	if ((err = nwam_enm_update_enabled(enmh, B_TRUE)) != NWAM_SUCCESS)
603 		return (err);
604 
605 	err = nwam_enable(NULL, enmh);
606 
607 	/* nwamd may not be running, that's okay. */
608 	if (err == NWAM_ERROR_BIND)
609 		return (NWAM_SUCCESS);
610 	else
611 		return (err);
612 }
613 
614 nwam_error_t
615 nwam_enm_disable(nwam_enm_handle_t enmh)
616 {
617 	nwam_error_t err;
618 	boolean_t manual, enabled;
619 
620 	assert(enmh != NULL);
621 
622 	/* Only enms with manual activation-mode can be disabled */
623 	if ((err = nwam_enm_is_manual(enmh, &manual)) != NWAM_SUCCESS)
624 		return (err);
625 	if (!manual)
626 		return (NWAM_ENTITY_NOT_MANUAL);
627 
628 	/* Make sure ENM is enabled */
629 	if ((err = nwam_enm_is_enabled(enmh, &enabled)) != NWAM_SUCCESS)
630 		return (err);
631 	if (!enabled)
632 		return (NWAM_SUCCESS);
633 
634 	if ((err = nwam_enm_update_enabled(enmh, B_FALSE)) != NWAM_SUCCESS)
635 		return (err);
636 
637 	err = nwam_disable(NULL, enmh);
638 
639 	/* nwamd may not be running, that's okay. */
640 	if (err == NWAM_ERROR_BIND)
641 		return (NWAM_SUCCESS);
642 	else
643 		return (err);
644 }
645 
646 nwam_error_t
647 nwam_enm_get_default_proplist(const char ***prop_list, uint_t *numvaluesp)
648 {
649 	return (nwam_get_default_proplist(enm_prop_table,
650 	    NWAM_TYPE_ANY, NWAM_CLASS_ANY, prop_list, numvaluesp));
651 }
652 
653 nwam_error_t
654 nwam_enm_get_state(nwam_enm_handle_t enmh, nwam_state_t *statep,
655     nwam_aux_state_t *auxp)
656 {
657 	return (nwam_get_state(NULL, enmh, statep, auxp));
658 }
659