8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libnwam / common / libnwam_ncp.c
blob75f5b5827a473fffbfe1d1a09b8b417227f1f0f9
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <assert.h>
28 #include <ctype.h>
29 #include <libgen.h>
30 #include <netdb.h>
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <libdladm.h>
43 #include "libnwam_impl.h"
44 #include <libnwam_priv.h>
45 #include <libnwam.h>
48 * Functions to support creating, modifying, destroying, querying the
49 * state of and changing the state of NCP (Network Configuration Profiles)
50 * and the NCUs (Network Configuration Units) that are contained in those
51 * NCP objects. An NCP is simply a container for a set of NCUs which represent
52 * the datalink and interface configuration preferences for the system.
53 * An NCP can consist a set of prioritized link NCUs, e.g. wired links preferred
54 * over wireless, a set of manually enabled/diasbled NCUs, or a combination
55 * of both. Interface NCUs inherit activation from their underlying links,
56 * so if wired is preferred over wireless and a cable is plugged in,
57 * the wired link NCU will be active, as will the IP interface NCU above it.
61 * The NCU property table is used to mapping property types to property name
62 * strings, their associated value types etc. The table is used for validation
63 * purposes, and for commit()ing and read()ing NCUs.
66 static nwam_error_t valid_type(nwam_value_t);
67 static nwam_error_t valid_class(nwam_value_t);
68 static nwam_error_t valid_ncp(nwam_value_t);
69 static nwam_error_t valid_priority_mode(nwam_value_t);
70 static nwam_error_t valid_ncu_activation_mode(nwam_value_t);
71 static nwam_error_t valid_link_autopush(nwam_value_t);
72 static nwam_error_t valid_link_mtu(nwam_value_t);
73 static nwam_error_t valid_ip_version(nwam_value_t);
74 static nwam_error_t valid_addrsrc_v4(nwam_value_t);
75 static nwam_error_t valid_addrsrc_v6(nwam_value_t);
77 struct nwam_prop_table_entry ncu_prop_table_entries[] = {
78 {NWAM_NCU_PROP_TYPE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1, valid_type,
79 "specifies the NCU type - valid values are \'datalink\' and \'ip\'",
80 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
81 {NWAM_NCU_PROP_CLASS, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
82 valid_class,
83 "specifies the NCU class - valid values are "
84 "\'phys\' and \'ip\'",
85 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
86 {NWAM_NCU_PROP_PARENT_NCP, NWAM_VALUE_TYPE_STRING, B_FALSE, 1, 1,
87 valid_ncp,
88 "specifies the parent NCP name",
89 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
90 {NWAM_NCU_PROP_ACTIVATION_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
91 valid_ncu_activation_mode,
92 "specifies the NCU activation mode - valid values are:\n"
93 "\'prioritized\' and \'manual\'",
94 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
95 {NWAM_NCU_PROP_ENABLED, NWAM_VALUE_TYPE_BOOLEAN, B_TRUE, 0, 1,
96 nwam_valid_boolean,
97 "specifies if manual NCU is to be enabled",
98 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
99 {NWAM_NCU_PROP_PRIORITY_GROUP, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
100 nwam_valid_uint64,
101 "specifies the priority grouping of NCUs - lower values are "
102 "prioritized, negative values are invalid",
103 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
104 {NWAM_NCU_PROP_PRIORITY_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
105 valid_priority_mode,
106 "specifies the mode of prioritization - valid values are:\n"
107 "\'exclusive\', \'shared\' and \'all\'",
108 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
109 {NWAM_NCU_PROP_LINK_MAC_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
110 nwam_valid_mac_addr,
111 "specifies MAC address of form aa:bb:cc:dd:ee:ff for the link",
112 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
113 {NWAM_NCU_PROP_LINK_AUTOPUSH, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
114 NWAM_MAX_NUM_VALUES, valid_link_autopush,
115 "specifies modules to autopush on link",
116 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
117 {NWAM_NCU_PROP_LINK_MTU, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
118 valid_link_mtu,
119 "specifies MTU for link",
120 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
121 {NWAM_NCU_PROP_IP_VERSION, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
122 NWAM_MAX_NUM_VALUES, valid_ip_version,
123 "specifies IP versions for IP NCU - valid values are:\n"
124 "\'ipv4\' and \'ipv6\'",
125 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
126 {NWAM_NCU_PROP_IPV4_ADDRSRC, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
127 NWAM_MAX_NUM_VALUES, valid_addrsrc_v4,
128 "specifies IPv4 address source(s) - valid values are:\n"
129 "\'dhcp\' and \'static\'",
130 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
131 {NWAM_NCU_PROP_IPV4_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
132 NWAM_MAX_NUM_VALUES, nwam_valid_host_v4,
133 "specifies static IPv4 host address(es)",
134 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
135 {NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
136 1, nwam_valid_route_v4,
137 "specifies per-interface default IPv4 route",
138 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
139 {NWAM_NCU_PROP_IPV6_ADDRSRC, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
140 NWAM_MAX_NUM_VALUES, valid_addrsrc_v6,
141 "specifies IPv6 address source(s) - valid values are:\n"
142 "\'dhcp\', \'autoconf\' and \'static\'.\n"
143 "\'dhcp\' and \'autoconf\' are mandatory values.",
144 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
145 {NWAM_NCU_PROP_IPV6_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
146 NWAM_MAX_NUM_VALUES, nwam_valid_host_v6,
147 "specifies static IPv6 host address(es)",
148 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
149 {NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
150 1, nwam_valid_route_v6,
151 "specifies per-interface default IPv6 route",
152 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE}
155 #define NWAM_NUM_NCU_PROPS (sizeof (ncu_prop_table_entries) / \
156 sizeof (*ncu_prop_table_entries))
158 struct nwam_prop_table ncu_prop_table =
159 { NWAM_NUM_NCU_PROPS, ncu_prop_table_entries };
161 nwam_error_t
162 nwam_ncp_get_name(nwam_ncp_handle_t ncph, char **namep)
164 return (nwam_get_name(ncph, namep));
167 static nwam_error_t
168 nwam_ncp_name_to_file(const char *name, char **filename)
170 assert(name != NULL && filename != NULL);
172 if ((*filename = malloc(MAXPATHLEN)) == NULL)
173 return (NWAM_NO_MEMORY);
175 (void) snprintf(*filename, MAXPATHLEN, "%s%s%s%s", NWAM_CONF_DIR,
176 NWAM_NCP_CONF_FILE_PRE, name, NWAM_NCP_CONF_FILE_SUF);
178 return (NWAM_SUCCESS);
181 /* ARGSUSED1 */
182 nwam_error_t
183 nwam_ncp_create(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
185 nwam_error_t err;
186 char *ncpfile;
188 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, name, ncphp))
189 != NWAM_SUCCESS)
190 return (err);
192 /* Create empty container for NCUs */
193 if ((err = nwam_ncp_name_to_file(name, &ncpfile))
194 != NWAM_SUCCESS) {
195 nwam_free(*ncphp);
196 *ncphp = NULL;
197 return (err);
200 if ((err = nwam_commit(ncpfile, *ncphp, flags)) != NWAM_SUCCESS) {
201 nwam_free(*ncphp);
202 *ncphp = NULL;
205 free(ncpfile);
207 return (err);
210 /* Used by libnwam_files.c */
211 nwam_error_t
212 nwam_ncp_file_to_name(const char *path, char **name)
214 char path_copy[MAXPATHLEN];
215 char *filename, *suffix;
217 assert(path != NULL && name != NULL);
219 /* Make a copy as basename(3c) may modify string */
220 (void) strlcpy(path_copy, path, MAXPATHLEN);
222 if ((*name = malloc(NWAM_MAX_NAME_LEN)) == NULL)
223 return (NWAM_NO_MEMORY);
225 if ((filename = basename(path_copy)) == NULL) {
226 free(*name);
227 return (NWAM_ENTITY_INVALID);
230 /* Ensure filename begins/ends with right prefix/suffix */
231 if (sscanf(filename, NWAM_NCP_CONF_FILE_PRE "%256[^\n]s", *name) < 1) {
232 free(*name);
233 return (NWAM_ENTITY_INVALID);
235 suffix = *name + strlen(*name) - strlen(NWAM_NCP_CONF_FILE_SUF);
236 if (strstr(*name, NWAM_NCP_CONF_FILE_SUF) != suffix) {
237 free(*name);
238 return (NWAM_ENTITY_INVALID);
240 suffix[0] = '\0';
242 return (NWAM_SUCCESS);
245 /* ARGSUSED1 */
246 nwam_error_t
247 nwam_ncp_read(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
249 char *filename;
250 nwam_error_t err;
252 assert(name != NULL && ncphp != NULL);
254 /* try to read the associated ncp configuration */
255 if ((err = nwam_ncp_name_to_file(name, &filename)) != NWAM_SUCCESS) {
256 *ncphp = NULL;
257 return (err);
260 err = nwam_read(NWAM_OBJECT_TYPE_NCP, filename, name, flags, ncphp);
261 free(filename);
262 return (err);
265 static nwam_error_t
266 nwam_ncu_get_parent_ncp_name(nwam_ncu_handle_t ncuh, char **parentnamep)
268 nwam_value_t parentval = NULL;
269 char *parentname;
270 nwam_error_t err;
272 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_PARENT_NCP,
273 &parentval)) != NWAM_SUCCESS ||
274 (err = nwam_value_get_string(parentval, &parentname))
275 != NWAM_SUCCESS ||
276 (*parentnamep = strdup(parentname)) == NULL) {
277 if (parentval != NULL)
278 nwam_value_free(parentval);
279 *parentnamep = NULL;
280 return (err);
282 nwam_value_free(parentval);
284 return (NWAM_SUCCESS);
287 static int
288 nwam_ncp_copy_callback(nwam_ncu_handle_t oldncuh, void *arg)
290 nwam_error_t err;
291 nwam_ncu_handle_t newncuh = NULL;
292 char *oldparent;
293 char *oldfilename = NULL, *newfilename = NULL;
294 nwam_ncp_handle_t newncph = (nwam_ncp_handle_t)arg;
295 nwam_value_t newparentval;
297 /* Get filenames for the new and old NCU's */
298 if ((err = nwam_ncu_get_parent_ncp_name(oldncuh, &oldparent))
299 != NWAM_SUCCESS)
300 return (err);
301 err = nwam_ncp_name_to_file(oldparent, &oldfilename);
302 free(oldparent);
303 if (err != NWAM_SUCCESS)
304 return (err);
305 if ((err = nwam_ncp_name_to_file(newncph->nwh_name, &newfilename))
306 != NWAM_SUCCESS)
307 goto fail;
309 /* new NCU name (and typedname) is the same as the old name */
310 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, oldncuh->nwh_name,
311 &newncuh)) != NWAM_SUCCESS)
312 goto fail;
313 /* Duplicate the old NCU's data */
314 if ((err = nwam_dup_object_list(oldncuh->nwh_data,
315 &(newncuh->nwh_data))) != NWAM_SUCCESS)
316 goto fail;
318 /* Update the parent property for the new NCU */
319 if ((err = nwam_value_create_string(newncph->nwh_name, &newparentval))
320 != NWAM_SUCCESS)
321 goto fail;
322 err = nwam_set_prop_value(newncuh->nwh_data, NWAM_NCU_PROP_PARENT_NCP,
323 newparentval);
324 nwam_value_free(newparentval);
325 if (err != NWAM_SUCCESS)
326 goto fail;
328 /* Save the new NCU */
329 err = nwam_commit(newfilename, newncuh, 0);
331 fail:
332 free(oldfilename);
333 free(newfilename);
334 nwam_ncu_free(newncuh);
335 return (err);
338 nwam_error_t
339 nwam_ncp_copy(nwam_ncp_handle_t oldncph, const char *newname,
340 nwam_ncp_handle_t *newncphp)
342 nwam_ncp_handle_t ncph;
343 nwam_error_t err;
344 int cb_ret;
346 assert(oldncph != NULL && newname != NULL && newncphp != NULL);
348 /* check if newname NCP already exists */
349 if (nwam_ncp_read(newname, 0, &ncph) == NWAM_SUCCESS) {
350 nwam_ncp_free(ncph);
351 *newncphp = NULL;
352 return (NWAM_ENTITY_EXISTS);
355 /* create new handle */
356 if ((err = nwam_ncp_create(newname, 0, newncphp)) != NWAM_SUCCESS)
357 return (err);
359 err = nwam_ncp_walk_ncus(oldncph, nwam_ncp_copy_callback, *newncphp,
360 NWAM_FLAG_NCU_TYPE_CLASS_ALL, &cb_ret);
361 if (err != NWAM_SUCCESS) {
362 /* remove the NCP even if any NCU's had already been copied */
363 (void) nwam_ncp_destroy(*newncphp, 0);
364 *newncphp = NULL;
365 if (err == NWAM_WALK_HALTED)
366 return (cb_ret);
367 else
368 return (err);
371 return (NWAM_SUCCESS);
375 * Convert type to flag
377 static uint64_t
378 nwam_ncu_type_to_flag(nwam_ncu_type_t type)
380 switch (type) {
381 case NWAM_NCU_TYPE_LINK:
382 return (NWAM_FLAG_NCU_TYPE_LINK);
383 case NWAM_NCU_TYPE_INTERFACE:
384 return (NWAM_FLAG_NCU_TYPE_INTERFACE);
385 case NWAM_NCU_TYPE_ANY:
386 return (NWAM_FLAG_NCU_TYPE_ALL);
387 default:
388 return (0);
393 * Convert class to flag
395 uint64_t
396 nwam_ncu_class_to_flag(nwam_ncu_class_t class)
398 switch (class) {
399 case NWAM_NCU_CLASS_PHYS:
400 return (NWAM_FLAG_NCU_CLASS_PHYS);
401 case NWAM_NCU_CLASS_IP:
402 return (NWAM_FLAG_NCU_CLASS_IP);
403 case NWAM_NCU_CLASS_ANY:
404 return (NWAM_FLAG_NCU_CLASS_ALL);
405 default:
406 return (0);
411 * Infer NCU type from NCU class
413 nwam_ncu_type_t
414 nwam_ncu_class_to_type(nwam_ncu_class_t class)
416 switch (class) {
417 case NWAM_NCU_CLASS_PHYS:
418 return (NWAM_NCU_TYPE_LINK);
419 case NWAM_NCU_CLASS_IP:
420 return (NWAM_NCU_TYPE_INTERFACE);
421 case NWAM_NCU_CLASS_ANY:
422 return (NWAM_NCU_TYPE_ANY);
423 default:
424 return (NWAM_NCU_TYPE_UNKNOWN);
429 * Make ncp active, deactivating any other active ncp.
431 nwam_error_t
432 nwam_ncp_enable(nwam_ncp_handle_t ncph)
434 nwam_error_t err;
435 char *name;
437 assert(ncph != NULL);
439 err = nwam_enable(NULL, ncph);
441 if (err == NWAM_ERROR_BIND) {
443 * nwamd is not running, set active_ncp property so when
444 * nwamd is next started, this NCP will be used.
446 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
447 return (err);
449 err = nwam_set_smf_string_property(NWAM_FMRI, NWAM_PG,
450 NWAM_PROP_ACTIVE_NCP, name);
451 free(name);
454 return (err);
457 /* Compare NCP names c1 and c2 using strcasecmp() */
458 static int
459 ncpname_cmp(const void *c1, const void *c2)
461 return (strcasecmp(*(const char **)c1, *(const char **)c2));
464 /* ARGSUSED1 */
465 nwam_error_t
466 nwam_walk_ncps(int (*cb)(nwam_ncp_handle_t, void *), void *data,
467 uint64_t flags, int *retp)
469 char *ncpname, **ncpfiles;
470 nwam_ncp_handle_t ncph;
471 nwam_error_t err;
472 nwam_value_t value;
473 void *objlist;
474 uint_t i, num_ncpfiles;
475 int ret = 0;
477 assert(cb != NULL);
479 if ((err = nwam_valid_flags(flags, NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
480 return (err);
482 * To get list of NCP files, call nwam_read_object_from_backend()
483 * with "parent" argument set to NULL. We get back an object list
484 * consisting of string arrays for each object type - NCP, ENM
485 * and location. We retrieve the NCP list, which corresponds to
486 * the set of NCP backend parent objects (these are files at present).
488 if ((err = nwam_read_object_from_backend(NULL, NULL, flags,
489 &objlist)) != NWAM_SUCCESS)
490 return (err);
492 if ((err = nwam_get_prop_value(objlist, NWAM_NCP_OBJECT_STRING, &value))
493 != NWAM_SUCCESS) {
494 nwam_free_object_list(objlist);
495 return (err);
497 if ((err = nwam_value_get_string_array(value, &ncpfiles,
498 &num_ncpfiles)) != NWAM_SUCCESS) {
499 nwam_value_free(value);
500 nwam_free_object_list(objlist);
501 return (err);
504 /* sort the NCP names alphabetically */
505 qsort(ncpfiles, num_ncpfiles, sizeof (char *), ncpname_cmp);
507 for (i = 0; i < num_ncpfiles; i++) {
508 if (nwam_ncp_file_to_name(ncpfiles[i], &ncpname)
509 != NWAM_SUCCESS)
510 continue;
511 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, ncpname,
512 &ncph)) != NWAM_SUCCESS) {
513 free(ncpname);
514 break;
516 ret = cb(ncph, data);
517 free(ncph);
518 free(ncpname);
519 if (ret != 0) {
520 err = NWAM_WALK_HALTED;
521 break;
524 nwam_value_free(value);
525 nwam_free_object_list(objlist);
527 if (retp != NULL)
528 *retp = ret;
529 return (err);
533 * Checks if NCP is read-only. Only NWAM_NCP_NAME_AUTOMATIC is read-only
534 * for all but the netadm user (which nwamd runs as).
536 nwam_error_t
537 nwam_ncp_get_read_only(nwam_ncp_handle_t ncph, boolean_t *readp)
539 nwam_error_t err;
540 char *name;
542 assert(ncph != NULL && readp != NULL);
544 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
545 return (err);
547 if (NWAM_NCP_AUTOMATIC(name))
548 *readp = !nwam_uid_is_special();
549 else
550 *readp = B_FALSE;
552 free(name);
553 return (NWAM_SUCCESS);
556 /* Checks if NCU is writable depending on its parent */
557 nwam_error_t
558 nwam_ncu_get_read_only(nwam_ncu_handle_t ncuh, boolean_t *readp)
560 nwam_error_t err;
561 nwam_ncp_handle_t ncph;
563 assert(ncuh != NULL && readp != NULL);
565 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
566 return (err);
568 err = nwam_ncp_get_read_only(ncph, readp);
569 nwam_ncp_free(ncph);
570 return (err);
573 /* Returns true if the NCP is active */
574 static boolean_t
575 nwam_ncp_is_active(nwam_ncp_handle_t ncph)
577 char *active_ncp, *name;
578 boolean_t ret;
580 assert(ncph != NULL);
583 * Determine which NCP is active via the nwamd/active_ncp property
584 * value. This allows us to determine which NCP is active even
585 * if nwamd is not running.
587 if (nwam_ncp_get_name(ncph, &name) != NWAM_SUCCESS ||
588 nwam_get_smf_string_property(NWAM_FMRI, NWAM_PG,
589 NWAM_PROP_ACTIVE_NCP, &active_ncp) != NWAM_SUCCESS)
590 return (B_FALSE);
592 ret = (strcmp(name, active_ncp) == 0);
594 free(active_ncp);
595 free(name);
597 return (ret);
600 nwam_error_t
601 nwam_ncp_destroy(nwam_ncp_handle_t ncph, uint64_t flags)
603 char *filename;
604 nwam_error_t err;
605 boolean_t read_only;
607 assert(ncph != NULL);
609 if ((err = nwam_ncp_get_read_only(ncph, &read_only)) != NWAM_SUCCESS)
610 return (err);
611 if (read_only)
612 return (NWAM_ENTITY_NOT_DESTROYABLE);
614 if (nwam_ncp_is_active(ncph))
615 return (NWAM_ENTITY_IN_USE);
617 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &filename))
618 != NWAM_SUCCESS)
619 return (err);
621 err = nwam_destroy(filename, ncph, flags);
622 free(filename);
624 return (NWAM_SUCCESS);
627 static nwam_error_t
628 nwam_ncu_internal_name_to_name(const char *internalname,
629 nwam_ncu_type_t *typep, char **namep)
631 char *prefixstr;
633 assert(internalname != NULL && namep != NULL);
635 if (strncasecmp(internalname, NWAM_NCU_LINK_NAME_PRE,
636 strlen(NWAM_NCU_LINK_NAME_PRE)) == 0) {
637 prefixstr = NWAM_NCU_LINK_NAME_PRE;
638 *typep = NWAM_NCU_TYPE_LINK;
639 } else if (strncasecmp(internalname, NWAM_NCU_INTERFACE_NAME_PRE,
640 strlen(NWAM_NCU_INTERFACE_NAME_PRE)) == 0) {
641 prefixstr = NWAM_NCU_INTERFACE_NAME_PRE;
642 *typep = NWAM_NCU_TYPE_INTERFACE;
643 } else {
644 return (NWAM_INVALID_ARG);
647 *namep = strdup(internalname + strlen(prefixstr));
648 if (*namep == NULL)
649 return (NWAM_NO_MEMORY);
650 return (NWAM_SUCCESS);
653 /* ARGSUSED2 */
654 static int
655 ncu_selectcb(struct nwam_handle *hp, uint64_t flags, void *data)
657 nwam_ncu_handle_t ncuh = hp;
658 nwam_value_t typeval = NULL, classval = NULL;
659 uint64_t type, class, matchflags, walkfilter;
661 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval)
662 != NWAM_SUCCESS ||
663 nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS, &classval)
664 != NWAM_SUCCESS) {
665 if (typeval != NULL)
666 nwam_value_free(typeval);
667 return (NWAM_INVALID_ARG);
669 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS ||
670 nwam_value_get_uint64(classval, &class) != NWAM_SUCCESS) {
671 nwam_value_free(typeval);
672 nwam_value_free(classval);
673 return (NWAM_INVALID_ARG);
676 matchflags = nwam_ncu_type_to_flag(type) |
677 nwam_ncu_class_to_flag(class);
678 nwam_value_free(typeval);
679 nwam_value_free(classval);
681 if ((walkfilter = (flags & NWAM_WALK_FILTER_MASK)) == 0)
682 walkfilter = NWAM_FLAG_NCU_TYPE_CLASS_ALL;
684 if (matchflags & walkfilter)
685 return (NWAM_SUCCESS);
686 return (NWAM_INVALID_ARG);
689 nwam_error_t
690 nwam_ncp_walk_ncus(nwam_ncp_handle_t ncph,
691 int(*cb)(nwam_ncu_handle_t, void *), void *data, uint64_t flags, int *retp)
693 char *ncpfile;
694 nwam_error_t err;
696 assert(ncph != NULL && cb != NULL);
698 if ((err = nwam_valid_flags(flags,
699 NWAM_FLAG_NCU_TYPE_CLASS_ALL | NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
700 return (err);
702 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
703 != NWAM_SUCCESS)
704 return (err);
706 err = nwam_walk(NWAM_OBJECT_TYPE_NCU, ncpfile, cb, data, flags,
707 retp, ncu_selectcb);
708 free(ncpfile);
710 return (err);
713 void
714 nwam_ncp_free(nwam_ncp_handle_t ncph)
716 nwam_free(ncph);
720 * Are ncu type and class compatible?
722 static boolean_t
723 nwam_ncu_type_class_compatible(nwam_ncu_type_t type, nwam_ncu_class_t class)
725 switch (type) {
726 case NWAM_NCU_TYPE_LINK:
727 return (class == NWAM_NCU_CLASS_PHYS);
728 case NWAM_NCU_TYPE_INTERFACE:
729 return (class == NWAM_NCU_CLASS_IP);
730 default:
731 return (B_FALSE);
735 /* Name to validate may be internal name. If so, convert it before validating */
736 static boolean_t
737 valid_ncu_name(const char *name)
739 char *n;
740 boolean_t ret;
741 nwam_ncu_type_t type;
743 if (nwam_ncu_internal_name_to_name(name, &type, &n) == NWAM_SUCCESS) {
745 ret = dladm_valid_linkname(n);
746 free(n);
747 } else {
748 ret = dladm_valid_linkname(name);
751 return (ret);
754 nwam_error_t
755 nwam_ncu_create(nwam_ncp_handle_t ncph, const char *name,
756 nwam_ncu_type_t type, nwam_ncu_class_t class, nwam_ncu_handle_t *ncuhp)
758 nwam_ncu_handle_t ncuh;
759 nwam_value_t typeval = NULL, classval = NULL, parentval = NULL;
760 nwam_value_t enabledval = NULL;
761 nwam_error_t err;
762 boolean_t read_only;
763 char *typedname;
765 assert(ncph != NULL && name != NULL && ncuhp != NULL);
767 if (!valid_ncu_name(name))
768 return (NWAM_INVALID_ARG);
770 if ((err = nwam_ncp_get_read_only(ncph, &read_only)) != NWAM_SUCCESS)
771 return (err);
772 if (read_only)
773 return (NWAM_ENTITY_READ_ONLY);
775 if (nwam_ncu_read(ncph, name, type, 0, &ncuh) == NWAM_SUCCESS) {
776 nwam_ncu_free(ncuh);
777 return (NWAM_ENTITY_EXISTS);
780 if (!valid_ncu_name(name) ||
781 !nwam_ncu_type_class_compatible(type, class))
782 return (NWAM_INVALID_ARG);
784 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname))
785 != NWAM_SUCCESS)
786 return (err);
788 /* Create handle */
789 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, typedname, ncuhp))
790 != NWAM_SUCCESS)
791 return (err);
792 free(typedname);
795 * Create new object list for NCU. The new NCU is initialized with
796 * the appropriate type and class.
798 if ((err = nwam_alloc_object_list(&(*ncuhp)->nwh_data)) != NWAM_SUCCESS)
799 goto finish;
801 if ((err = nwam_value_create_uint64(type, &typeval))
802 != NWAM_SUCCESS ||
803 (err = nwam_value_create_uint64(class, &classval))
804 != NWAM_SUCCESS ||
805 (err = nwam_value_create_string(ncph->nwh_name, &parentval))
806 != NWAM_SUCCESS ||
807 (err = nwam_value_create_boolean(B_TRUE, &enabledval))
808 != NWAM_SUCCESS) {
809 goto finish;
811 if ((err = nwam_set_prop_value((*ncuhp)->nwh_data, NWAM_NCU_PROP_TYPE,
812 typeval)) != NWAM_SUCCESS ||
813 (err = nwam_set_prop_value((*ncuhp)->nwh_data, NWAM_NCU_PROP_CLASS,
814 classval)) != NWAM_SUCCESS ||
815 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
816 NWAM_NCU_PROP_PARENT_NCP, parentval)) != NWAM_SUCCESS ||
817 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
818 NWAM_NCU_PROP_ENABLED, enabledval)) != NWAM_SUCCESS) {
819 goto finish;
822 /* Set default IP, datalink properties */
823 if (type == NWAM_NCU_TYPE_INTERFACE && class == NWAM_NCU_CLASS_IP) {
825 uint64_t ver[] = { IPV4_VERSION, IPV6_VERSION };
826 uint64_t v6src[] = { NWAM_ADDRSRC_DHCP, NWAM_ADDRSRC_AUTOCONF };
827 uint_t vercnt = 2, v6srccnt = 2;
828 nwam_value_t ipver = NULL, v4addrsrc = NULL, v6addrsrc = NULL;
830 if ((err = nwam_value_create_uint64_array(ver, vercnt, &ipver))
831 != NWAM_SUCCESS ||
832 (err = nwam_value_create_uint64(NWAM_ADDRSRC_DHCP,
833 &v4addrsrc)) != NWAM_SUCCESS ||
834 (err = nwam_value_create_uint64_array(v6src, v6srccnt,
835 &v6addrsrc)) != NWAM_SUCCESS) {
836 nwam_value_free(ipver);
837 nwam_value_free(v4addrsrc);
838 goto finish;
840 if ((err = nwam_set_prop_value((*ncuhp)->nwh_data,
841 NWAM_NCU_PROP_IP_VERSION, ipver)) == NWAM_SUCCESS &&
842 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
843 NWAM_NCU_PROP_IPV4_ADDRSRC, v4addrsrc)) == NWAM_SUCCESS) {
844 err = nwam_set_prop_value((*ncuhp)->nwh_data,
845 NWAM_NCU_PROP_IPV6_ADDRSRC, v6addrsrc);
847 nwam_value_free(ipver);
848 nwam_value_free(v4addrsrc);
849 nwam_value_free(v6addrsrc);
850 } else {
851 nwam_value_t actval = NULL;
852 if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL,
853 &actval)) != NWAM_SUCCESS)
854 goto finish;
855 err = nwam_set_prop_value((*ncuhp)->nwh_data,
856 NWAM_NCU_PROP_ACTIVATION_MODE, actval);
857 nwam_value_free(actval);
860 finish:
861 nwam_value_free(typeval);
862 nwam_value_free(classval);
863 nwam_value_free(parentval);
864 nwam_value_free(enabledval);
865 if (err != NWAM_SUCCESS) {
866 nwam_ncu_free(*ncuhp);
867 *ncuhp = NULL;
869 return (err);
872 nwam_error_t
873 nwam_ncu_read(nwam_ncp_handle_t ncph, const char *name,
874 nwam_ncu_type_t type, uint64_t flags, nwam_ncu_handle_t *ncuhp)
876 char *ncpfile, *typedname;
877 nwam_error_t err, err_ip, err_link;
878 nwam_ncu_handle_t ncuh_ip, ncuh_link;
880 assert(ncph != NULL && name != NULL && ncuhp != NULL);
882 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
883 != NWAM_SUCCESS)
884 return (err);
886 if (type == NWAM_NCU_TYPE_ANY) {
888 free(ncpfile);
891 * If we get to this point, we have discovered that no
892 * NCU type is discernable from name or type arguments.
893 * Either exactly one NCU called name must exist of either
894 * type, or the operation should fail.
896 err_ip = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_INTERFACE,
897 flags, &ncuh_ip);
898 err_link = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK,
899 flags, &ncuh_link);
901 *ncuhp = NULL;
903 if (err_ip == NWAM_SUCCESS && err_link == NWAM_SUCCESS) {
904 nwam_ncu_free(ncuh_ip);
905 nwam_ncu_free(ncuh_link);
906 err = NWAM_ENTITY_MULTIPLE_VALUES;
907 } else if (err_ip != NWAM_SUCCESS && err_link != NWAM_SUCCESS) {
908 err = NWAM_ENTITY_NOT_FOUND;
909 } else {
910 if (err_ip == NWAM_SUCCESS) {
911 *ncuhp = ncuh_ip;
912 } else {
913 *ncuhp = ncuh_link;
915 err = NWAM_SUCCESS;
918 return (err);
920 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname)) !=
921 NWAM_SUCCESS) {
922 free(ncpfile);
923 return (err);
925 err = nwam_read(NWAM_OBJECT_TYPE_NCU, ncpfile, typedname, flags, ncuhp);
927 free(typedname);
928 free(ncpfile);
930 return (err);
933 nwam_error_t
934 nwam_ncu_get_name(nwam_ncu_handle_t ncuh, char **namep)
936 nwam_ncu_type_t type;
938 assert(ncuh != NULL && namep != NULL);
940 return (nwam_ncu_internal_name_to_name(ncuh->nwh_name, &type, namep));
943 nwam_error_t
944 nwam_ncu_name_to_typed_name(const char *name, nwam_ncu_type_t type,
945 char **typednamep)
947 char *prefixstr;
948 size_t typednamesz;
950 assert(name != NULL && typednamep != NULL);
952 switch (type) {
953 case NWAM_NCU_TYPE_INTERFACE:
954 prefixstr = NWAM_NCU_INTERFACE_NAME_PRE;
955 break;
956 case NWAM_NCU_TYPE_LINK:
957 prefixstr = NWAM_NCU_LINK_NAME_PRE;
958 break;
959 default:
960 return (NWAM_INVALID_ARG);
962 typednamesz = strlen(name) + strlen(prefixstr) + 1;
963 if ((*typednamep = malloc(typednamesz)) == NULL)
964 return (NWAM_NO_MEMORY);
966 /* Name may be already qualified by type */
967 if (strncasecmp(prefixstr, name, strlen(prefixstr)) == 0) {
968 (void) snprintf(*typednamep, typednamesz, "%s", name);
969 } else {
970 (void) snprintf(*typednamep, typednamesz, "%s%s",
971 prefixstr, name);
974 return (NWAM_SUCCESS);
977 nwam_error_t
978 nwam_ncu_typed_name_to_name(const char *typed_name, nwam_ncu_type_t *typep,
979 char **name)
981 return (nwam_ncu_internal_name_to_name(typed_name, typep, name));
984 void
985 nwam_ncu_free(nwam_ncu_handle_t ncuh)
987 nwam_free(ncuh);
990 nwam_error_t
991 nwam_ncu_copy(nwam_ncu_handle_t oldncuh, const char *newname,
992 nwam_ncu_handle_t *newncuhp)
994 nwam_ncp_handle_t ncph;
995 nwam_ncu_handle_t ncuh;
996 nwam_error_t err;
997 nwam_value_t typeval;
998 uint64_t type;
999 char *typednewname;
1001 assert(oldncuh != NULL && newname != NULL && newncuhp != NULL);
1003 if (nwam_ncu_get_prop_value(oldncuh, NWAM_NCU_PROP_TYPE,
1004 &typeval) != NWAM_SUCCESS) {
1005 return (NWAM_INVALID_ARG);
1007 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1008 nwam_value_free(typeval);
1009 return (NWAM_INVALID_ARG);
1011 nwam_value_free(typeval);
1013 /* check if newname NCU already exists */
1014 if ((err = nwam_ncu_get_ncp(oldncuh, &ncph)) != NWAM_SUCCESS)
1015 return (err);
1016 if (nwam_ncu_read(ncph, newname, type, 0, &ncuh) == NWAM_SUCCESS) {
1017 nwam_ncu_free(ncuh);
1018 nwam_ncp_free(ncph);
1019 return (NWAM_ENTITY_EXISTS);
1021 nwam_ncp_free(ncph);
1023 if ((err = nwam_ncu_name_to_typed_name(newname, type, &typednewname))
1024 != NWAM_SUCCESS)
1025 return (err);
1027 err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, typednewname, newncuhp);
1028 free(typednewname);
1029 if (err != NWAM_SUCCESS)
1030 return (err);
1031 if ((err = nwam_dup_object_list(oldncuh->nwh_data,
1032 &((*newncuhp)->nwh_data))) != NWAM_SUCCESS) {
1033 free(*newncuhp);
1034 *newncuhp = NULL;
1035 return (err);
1038 return (NWAM_SUCCESS);
1041 nwam_error_t
1042 nwam_ncu_delete_prop(nwam_ncu_handle_t ncuh, const char *propname)
1044 boolean_t ro_ncu, ro_prop;
1045 nwam_error_t err;
1046 void *olddata;
1048 assert(ncuh != NULL && propname != NULL);
1050 if ((err = nwam_ncu_get_read_only(ncuh, &ro_ncu)) != NWAM_SUCCESS ||
1051 (err = nwam_ncu_prop_read_only(propname, &ro_prop)) != NWAM_SUCCESS)
1052 return (err);
1053 if (ro_ncu || ro_prop)
1054 return (NWAM_ENTITY_READ_ONLY);
1057 * Duplicate data, remove property and validate. If validation
1058 * fails, revert to data duplicated prior to remove.
1060 if ((err = nwam_dup_object_list(ncuh->nwh_data, &olddata))
1061 != NWAM_SUCCESS)
1062 return (err);
1063 if ((err = nwam_delete_prop(ncuh->nwh_data, propname))
1064 != NWAM_SUCCESS) {
1065 nwam_free_object_list(ncuh->nwh_data);
1066 ncuh->nwh_data = olddata;
1067 return (err);
1069 if ((err = nwam_ncu_validate(ncuh, NULL)) != NWAM_SUCCESS) {
1070 nwam_free_object_list(ncuh->nwh_data);
1071 ncuh->nwh_data = olddata;
1072 return (err);
1074 nwam_free_object_list(olddata);
1076 return (NWAM_SUCCESS);
1079 nwam_error_t
1080 nwam_ncu_set_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1081 nwam_value_t value)
1083 boolean_t ro_ncu, ro_prop;
1084 nwam_error_t err;
1085 nwam_ncp_handle_t ncph;
1087 assert(ncuh != NULL && propname != NULL && value != NULL);
1089 if ((err = nwam_ncu_get_read_only(ncuh, &ro_ncu)) != NWAM_SUCCESS ||
1090 (err = nwam_ncu_prop_read_only(propname, &ro_prop)) != NWAM_SUCCESS)
1091 return (err);
1092 if (ro_ncu || ro_prop)
1093 return (NWAM_ENTITY_READ_ONLY);
1095 err = nwam_ncu_get_ncp(ncuh, &ncph);
1096 if (err != NWAM_SUCCESS && err != NWAM_INVALID_ARG) {
1098 * If "parent" property doesn't exist, NWAM_INVALID_ARG
1099 * is returned. Allow the setting to continue.
1101 return (err);
1103 nwam_ncp_free(ncph);
1105 /* Need to ensure property, type and value are valid */
1106 if ((err = nwam_ncu_validate_prop(ncuh, propname, value))
1107 != NWAM_SUCCESS)
1108 return (err);
1110 return (nwam_set_prop_value(ncuh->nwh_data, propname, value));
1113 nwam_error_t
1114 nwam_ncu_get_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1115 nwam_value_t *valuep)
1117 assert(ncuh != NULL && propname != NULL && valuep != NULL);
1119 return (nwam_get_prop_value(ncuh->nwh_data, propname, valuep));
1122 nwam_error_t
1123 nwam_ncu_walk_props(nwam_ncu_handle_t ncuh,
1124 int (*cb)(const char *, nwam_value_t, void *),
1125 void *data, uint64_t flags, int *retp)
1127 return (nwam_walk_props(ncuh, cb, data, flags, retp));
1130 nwam_error_t
1131 nwam_ncu_get_ncp(nwam_ncu_handle_t ncuh, nwam_ncp_handle_t *ncphp)
1133 nwam_error_t err;
1134 char *parentname = NULL;
1136 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &parentname))
1137 != NWAM_SUCCESS ||
1138 (err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, parentname, ncphp))
1139 != NWAM_SUCCESS) {
1140 if (parentname != NULL)
1141 free(parentname);
1142 return (err);
1144 free(parentname);
1146 return (NWAM_SUCCESS);
1149 nwam_error_t
1150 nwam_ncu_commit(nwam_ncu_handle_t ncuh, uint64_t flags)
1152 nwam_error_t err;
1153 boolean_t read_only;
1154 char *ncpfile, *ncpname;
1156 assert(ncuh != NULL && ncuh->nwh_data != NULL);
1158 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1159 return (err);
1160 if (read_only)
1161 return (NWAM_ENTITY_READ_ONLY);
1163 if ((err = nwam_ncu_validate(ncuh, NULL)) != NWAM_SUCCESS ||
1164 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1165 != NWAM_SUCCESS)
1166 return (err);
1168 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile)) != NWAM_SUCCESS) {
1169 free(ncpname);
1170 return (err);
1173 err = nwam_commit(ncpfile, ncuh, flags);
1175 free(ncpname);
1176 free(ncpfile);
1178 return (err);
1180 /* Get the NCU type */
1181 nwam_error_t
1182 nwam_ncu_get_ncu_type(nwam_ncu_handle_t ncuh, nwam_ncu_type_t *typep)
1184 nwam_error_t err;
1185 nwam_value_t typeval;
1186 uint64_t type;
1188 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval))
1189 != NWAM_SUCCESS)
1190 return (err);
1191 err = nwam_value_get_uint64(typeval, &type);
1192 nwam_value_free(typeval);
1193 if (err != NWAM_SUCCESS)
1194 return (err);
1196 *typep = type;
1197 return (NWAM_SUCCESS);
1200 /* Get the NCU class */
1201 nwam_error_t
1202 nwam_ncu_get_ncu_class(nwam_ncu_handle_t ncuh, nwam_ncu_class_t *classp)
1204 nwam_error_t err;
1205 nwam_value_t classval;
1206 uint64_t class;
1208 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS,
1209 &classval)) != NWAM_SUCCESS)
1210 return (err);
1211 err = nwam_value_get_uint64(classval, &class);
1212 nwam_value_free(classval);
1213 if (err != NWAM_SUCCESS)
1214 return (err);
1216 *classp = class;
1217 return (NWAM_SUCCESS);
1221 * Determine if the NCU has manual activation-mode or not.
1223 nwam_error_t
1224 nwam_ncu_is_manual(nwam_ncu_handle_t ncuh, boolean_t *manualp)
1226 nwam_error_t err;
1227 nwam_value_t actval;
1228 uint64_t activation;
1230 assert(ncuh != NULL);
1232 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ACTIVATION_MODE,
1233 &actval)) != NWAM_SUCCESS)
1234 return (err);
1235 err = nwam_value_get_uint64(actval, &activation);
1236 nwam_value_free(actval);
1237 if (err != NWAM_SUCCESS)
1238 return (err);
1240 if (activation == NWAM_ACTIVATION_MODE_MANUAL)
1241 *manualp = B_TRUE;
1242 else
1243 *manualp = B_FALSE;
1244 return (NWAM_SUCCESS);
1247 /* Determine if NCU is enabled or not */
1248 static nwam_error_t
1249 nwam_ncu_is_enabled(nwam_ncu_handle_t ncuh, boolean_t *enabledp)
1251 nwam_error_t err;
1252 nwam_value_t enabledval;
1254 assert(ncuh != NULL);
1256 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED,
1257 &enabledval)) != NWAM_SUCCESS)
1258 return (err);
1259 err = nwam_value_get_boolean(enabledval, enabledp);
1260 nwam_value_free(enabledval);
1261 return (err);
1264 /* Update the enabled property */
1265 static nwam_error_t
1266 nwam_ncu_update_enabled(nwam_ncu_handle_t ncuh, boolean_t enabled)
1268 nwam_error_t err;
1269 nwam_value_t enabledval;
1271 if ((err = nwam_value_create_boolean(enabled, &enabledval))
1272 != NWAM_SUCCESS)
1273 return (err);
1274 err = nwam_set_prop_value(ncuh->nwh_data, NWAM_NCU_PROP_ENABLED,
1275 enabledval);
1276 nwam_value_free(enabledval);
1277 if (err != NWAM_SUCCESS)
1278 return (err);
1279 return (nwam_ncu_commit(ncuh, NWAM_FLAG_ENTITY_ENABLE));
1283 * Make ncu active; fails if the NCU's parent NCP is not active.
1285 nwam_error_t
1286 nwam_ncu_enable(nwam_ncu_handle_t ncuh)
1288 char *ncpname = NULL;
1289 nwam_error_t err;
1290 nwam_ncu_type_t type;
1291 boolean_t read_only, enabled, manual;
1293 assert(ncuh != NULL);
1295 /* Don't allow NCUs of Automatic NCP to be enabled */
1296 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1297 return (err);
1298 if (read_only)
1299 return (NWAM_ENTITY_NOT_MANUAL);
1301 /* Link NCUs with manual activation-mode or IP NCUs can be enabled */
1302 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1303 return (err);
1305 if (type == NWAM_NCU_TYPE_LINK) {
1306 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1307 return (err);
1308 if (!manual)
1309 return (NWAM_ENTITY_NOT_MANUAL);
1312 /* Make sure NCU is not enabled */
1313 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1314 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1315 != NWAM_SUCCESS)
1316 return (err);
1318 if (enabled) {
1319 free(ncpname);
1320 return (NWAM_SUCCESS);
1323 if ((err = nwam_ncu_update_enabled(ncuh, B_TRUE)) != NWAM_SUCCESS) {
1324 free(ncpname);
1325 return (err);
1328 err = nwam_enable(ncpname, ncuh);
1329 free(ncpname);
1331 /* nwamd may not be running, that's okay. */
1332 if (err == NWAM_ERROR_BIND)
1333 return (NWAM_SUCCESS);
1334 else
1335 return (err);
1339 * Disable ncu; fails if the NCU's parent NCP is not active, or if the
1340 * NCU is not currently active.
1342 nwam_error_t
1343 nwam_ncu_disable(nwam_ncu_handle_t ncuh)
1345 char *ncpname = NULL;
1346 nwam_error_t err;
1347 nwam_ncu_type_t type;
1348 boolean_t read_only, enabled, manual;
1350 assert(ncuh != NULL);
1352 /* Don't allow NCUs of Automatic NCP to be disabled */
1353 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1354 return (err);
1355 if (read_only)
1356 return (NWAM_ENTITY_NOT_MANUAL);
1358 /* Link NCUs with manual activation-mode or IP NCUs can be disabled */
1359 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1360 return (err);
1362 if (type == NWAM_NCU_TYPE_LINK) {
1363 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1364 return (err);
1365 if (!manual)
1366 return (NWAM_ENTITY_NOT_MANUAL);
1369 /* Make sure NCU is enabled */
1370 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1371 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1372 != NWAM_SUCCESS)
1373 return (err);
1375 if (!enabled) {
1376 free(ncpname);
1377 return (NWAM_SUCCESS);
1380 if ((err = nwam_ncu_update_enabled(ncuh, B_FALSE)) != NWAM_SUCCESS) {
1381 free(ncpname);
1382 return (err);
1385 err = nwam_disable(ncpname, ncuh);
1386 free(ncpname);
1388 /* nwamd may not be running, that's okay. */
1389 if (err == NWAM_ERROR_BIND)
1390 return (NWAM_SUCCESS);
1391 else
1392 return (err);
1395 nwam_error_t
1396 nwam_ncu_destroy(nwam_ncu_handle_t ncuh, uint64_t flags)
1398 char *ncpname, *ncpfile;
1399 boolean_t read_only;
1400 nwam_error_t err;
1402 assert(ncuh != NULL);
1404 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1405 return (err);
1406 if (read_only)
1407 return (NWAM_ENTITY_NOT_DESTROYABLE);
1409 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1410 != NWAM_SUCCESS)
1411 return (err);
1412 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile))
1413 != NWAM_SUCCESS) {
1414 free(ncpname);
1415 return (err);
1418 err = nwam_destroy(ncpfile, ncuh, flags);
1420 free(ncpname);
1421 free(ncpfile);
1423 return (err);
1426 nwam_error_t
1427 nwam_ncu_get_prop_description(const char *propname, const char **descriptionp)
1429 return (nwam_get_prop_description(ncu_prop_table, propname,
1430 descriptionp));
1433 /* Get expected property data type */
1434 nwam_error_t
1435 nwam_ncu_get_prop_type(const char *propname, nwam_value_type_t *typep)
1437 return (nwam_get_prop_type(ncu_prop_table, propname, typep));
1440 nwam_error_t
1441 nwam_ncu_prop_read_only(const char *propname, boolean_t *readp)
1443 if ((*readp = NWAM_NCU_PROP_SETONCE(propname)) == B_TRUE)
1444 return (NWAM_SUCCESS);
1446 return (nwam_prop_read_only(ncu_prop_table, propname, readp));
1449 nwam_error_t
1450 nwam_ncu_prop_multivalued(const char *propname, boolean_t *multip)
1452 return (nwam_prop_multivalued(ncu_prop_table, propname, multip));
1456 * Ensure that the properties in the ncu, determined by that ncu's
1457 * type and class, belong there.
1459 static nwam_error_t
1460 nwam_ncu_validate_prop_membership(nwam_ncu_handle_t ncuh, const char *propname)
1462 struct nwam_prop_table_entry *pte;
1463 nwam_value_t typeval, classval;
1464 uint64_t type, class;
1465 uint64_t typeflags = 0, classflags = 0;
1467 /* Get type/class from ncu */
1468 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval)
1469 != NWAM_SUCCESS)
1470 return (NWAM_ENTITY_INVALID);
1471 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1472 nwam_value_free(typeval);
1473 return (NWAM_ENTITY_INVALID);
1475 typeflags = nwam_ncu_type_to_flag((nwam_ncu_type_t)type);
1476 nwam_value_free(typeval);
1478 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS, &classval)
1479 != NWAM_SUCCESS)
1480 return (NWAM_ENTITY_INVALID);
1481 if (nwam_value_get_uint64(classval, &class) != NWAM_SUCCESS) {
1482 nwam_value_free(classval);
1483 return (NWAM_ENTITY_INVALID);
1485 classflags = nwam_ncu_class_to_flag((nwam_ncu_class_t)class);
1486 nwam_value_free(classval);
1488 if ((pte = nwam_get_prop_table_entry(ncu_prop_table, propname)) == NULL)
1489 return (NWAM_INVALID_ARG);
1491 if (typeflags & pte->prop_type_membership &&
1492 classflags & pte->prop_class_membership) {
1493 return (NWAM_SUCCESS);
1494 } else {
1495 return (NWAM_ENTITY_INVALID_MEMBER);
1499 /* Validate property's ncu membership and type, number and range of values */
1500 nwam_error_t
1501 nwam_ncu_validate_prop(nwam_ncu_handle_t ncuh, const char *propname,
1502 nwam_value_t value)
1504 nwam_error_t err;
1506 assert(ncuh != NULL && propname != NULL);
1508 /* First, determine if this property is valid for this ncu */
1509 if ((err = nwam_ncu_validate_prop_membership(ncuh, propname))
1510 != NWAM_SUCCESS)
1511 return (err);
1513 return (nwam_validate_prop(ncu_prop_table, ncuh, propname, value));
1516 /* Property-specific value validation functions follow */
1518 static nwam_error_t
1519 valid_type(nwam_value_t value)
1521 uint64_t type;
1523 if (nwam_value_get_uint64(value, &type) != NWAM_SUCCESS ||
1524 type > NWAM_NCU_TYPE_INTERFACE)
1525 return (NWAM_ENTITY_INVALID_VALUE);
1526 return (NWAM_SUCCESS);
1529 static nwam_error_t
1530 valid_class(nwam_value_t value)
1532 uint64_t class;
1534 if (nwam_value_get_uint64(value, &class) != NWAM_SUCCESS ||
1535 class > NWAM_NCU_CLASS_IP)
1536 return (NWAM_ENTITY_INVALID_VALUE);
1537 return (NWAM_SUCCESS);
1540 static nwam_error_t
1541 valid_ncp(nwam_value_t value)
1543 char *ncp;
1545 if (nwam_value_get_string(value, &ncp) != NWAM_SUCCESS)
1546 return (NWAM_ENTITY_INVALID_VALUE);
1547 return (NWAM_SUCCESS);
1550 static nwam_error_t
1551 valid_priority_mode(nwam_value_t value)
1553 uint64_t priority_mode;
1555 if (nwam_value_get_uint64(value, &priority_mode) != NWAM_SUCCESS ||
1556 priority_mode > NWAM_PRIORITY_MODE_ALL)
1557 return (NWAM_ENTITY_INVALID_VALUE);
1558 return (NWAM_SUCCESS);
1561 static nwam_error_t
1562 valid_ncu_activation_mode(nwam_value_t value)
1564 uint64_t activation_mode;
1566 if (nwam_value_get_uint64(value, &activation_mode) != NWAM_SUCCESS)
1567 return (NWAM_ENTITY_INVALID_VALUE);
1569 switch (activation_mode) {
1570 case NWAM_ACTIVATION_MODE_MANUAL:
1571 case NWAM_ACTIVATION_MODE_PRIORITIZED:
1572 return (NWAM_SUCCESS);
1574 return (NWAM_ENTITY_INVALID_VALUE);
1577 /* ARGSUSED0 */
1578 static nwam_error_t
1579 valid_link_autopush(nwam_value_t value)
1581 return (NWAM_SUCCESS);
1584 static nwam_error_t
1585 valid_ip_version(nwam_value_t value)
1587 uint64_t *versions;
1588 uint_t i, numvalues;
1590 if (nwam_value_get_uint64_array(value, &versions, &numvalues)
1591 != NWAM_SUCCESS)
1592 return (NWAM_ENTITY_INVALID_VALUE);
1594 for (i = 0; i < numvalues; i++) {
1595 if (versions[i] != IPV4_VERSION &&
1596 versions[i] != IPV6_VERSION)
1597 return (NWAM_ENTITY_INVALID_VALUE);
1599 return (NWAM_SUCCESS);
1602 static nwam_error_t
1603 valid_addrsrc_v4(nwam_value_t value)
1605 uint64_t *addrsrc;
1606 uint_t i, numvalues;
1608 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1609 != NWAM_SUCCESS)
1610 return (NWAM_ENTITY_INVALID_VALUE);
1612 for (i = 0; i < numvalues; i++) {
1613 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1614 addrsrc[i] != NWAM_ADDRSRC_STATIC)
1615 return (NWAM_ENTITY_INVALID_VALUE);
1617 return (NWAM_SUCCESS);
1620 static nwam_error_t
1621 valid_addrsrc_v6(nwam_value_t value)
1623 uint64_t *addrsrc;
1624 uint_t i, numvalues;
1625 boolean_t dhcp_found = B_FALSE, autoconf_found = B_FALSE;
1627 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1628 != NWAM_SUCCESS)
1629 return (NWAM_ENTITY_INVALID_VALUE);
1631 for (i = 0; i < numvalues; i++) {
1632 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1633 addrsrc[i] != NWAM_ADDRSRC_STATIC &&
1634 addrsrc[i] != NWAM_ADDRSRC_AUTOCONF)
1635 return (NWAM_ENTITY_INVALID_VALUE);
1636 if (addrsrc[i] == NWAM_ADDRSRC_DHCP)
1637 dhcp_found = B_TRUE;
1638 if (addrsrc[i] == NWAM_ADDRSRC_AUTOCONF)
1639 autoconf_found = B_TRUE;
1642 * DHCP and AUTOCONF need to be specified as v6 address sources
1643 * since there is no way to switch them off in NWAM at present.
1645 if (dhcp_found && autoconf_found)
1646 return (NWAM_SUCCESS);
1647 else
1648 return (NWAM_ENTITY_INVALID_VALUE);
1651 /* ARGSUSED0 */
1652 static nwam_error_t
1653 valid_link_mtu(nwam_value_t value)
1655 return (NWAM_SUCCESS);
1658 nwam_error_t
1659 nwam_ncu_validate(nwam_ncu_handle_t ncuh, const char **errpropp)
1661 return (nwam_validate(ncu_prop_table, ncuh, errpropp));
1665 * Given the ncu type and ncu class, return the list of properties that needs
1666 * to be set. Note this list is a complete property list that includes both
1667 * the required ones and the optional ones. Caller needs to free prop_list.
1669 nwam_error_t
1670 nwam_ncu_get_default_proplist(nwam_ncu_type_t type, nwam_ncu_class_t class,
1671 const char ***prop_list, uint_t *numvalues)
1673 uint64_t typeflags = nwam_ncu_type_to_flag(type);
1674 uint64_t classflags = nwam_ncu_class_to_flag(class);
1676 return (nwam_get_default_proplist(ncu_prop_table, typeflags,
1677 classflags, prop_list, numvalues));
1680 nwam_error_t
1681 nwam_ncp_get_state(nwam_ncp_handle_t ncph, nwam_state_t *statep,
1682 nwam_aux_state_t *auxp)
1684 return (nwam_get_state(ncph->nwh_name, ncph, statep, auxp));
1687 nwam_error_t
1688 nwam_ncu_get_state(nwam_ncu_handle_t ncuh, nwam_state_t *statep,
1689 nwam_aux_state_t *auxp)
1691 nwam_ncp_handle_t ncph;
1692 char *ncpname;
1693 nwam_error_t err;
1695 assert(ncuh != NULL);
1697 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
1698 return (err);
1699 if (!nwam_ncp_is_active(ncph)) {
1700 nwam_ncp_free(ncph);
1701 return (NWAM_ENTITY_INVALID);
1703 nwam_ncp_free(ncph);
1705 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1706 != NWAM_SUCCESS)
1707 return (err);
1709 err = nwam_request_state(NWAM_OBJECT_TYPE_NCU, ncuh->nwh_name, ncpname,
1710 statep, auxp);
1711 free(ncpname);
1712 return (err);
1715 nwam_error_t
1716 nwam_ncp_get_active_priority_group(int64_t *priorityp)
1718 return (nwam_request_active_priority_group(priorityp));