Merge commit 'b31320a79e2054c6739b5229259dbf98f3afc547' into merges
[unleashed.git] / usr / src / lib / libnwam / common / libnwam_ncp.c
blobb61dc01e89d74b692a4d88a9a77b47c06c8b6f8e
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.
25 * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
28 #include <assert.h>
29 #include <ctype.h>
30 #include <libgen.h>
31 #include <netdb.h>
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <strings.h>
41 #include <unistd.h>
42 #include <libdladm.h>
43 #include <libipadm.h>
45 #include "libnwam_impl.h"
46 #include <libnwam_priv.h>
47 #include <libnwam.h>
50 * Functions to support creating, modifying, destroying, querying the
51 * state of and changing the state of NCP (Network Configuration Profiles)
52 * and the NCUs (Network Configuration Units) that are contained in those
53 * NCP objects. An NCP is simply a container for a set of NCUs which represent
54 * the datalink and interface configuration preferences for the system.
55 * An NCP can consist a set of prioritized link NCUs, e.g. wired links preferred
56 * over wireless, a set of manually enabled/diasbled NCUs, or a combination
57 * of both. Interface NCUs inherit activation from their underlying links,
58 * so if wired is preferred over wireless and a cable is plugged in,
59 * the wired link NCU will be active, as will the IP interface NCU above it.
63 * The NCU property table is used to mapping property types to property name
64 * strings, their associated value types etc. The table is used for validation
65 * purposes, and for commit()ing and read()ing NCUs.
68 static nwam_error_t valid_type(nwam_value_t);
69 static nwam_error_t valid_class(nwam_value_t);
70 static nwam_error_t valid_ncp(nwam_value_t);
71 static nwam_error_t valid_priority_mode(nwam_value_t);
72 static nwam_error_t valid_ncu_activation_mode(nwam_value_t);
73 static nwam_error_t valid_link_autopush(nwam_value_t);
74 static nwam_error_t valid_link_mtu(nwam_value_t);
75 static nwam_error_t valid_ip_version(nwam_value_t);
76 static nwam_error_t valid_addrsrc_v4(nwam_value_t);
77 static nwam_error_t valid_addrsrc_v6(nwam_value_t);
78 static nwam_error_t valid_reqhost(nwam_value_t);
80 struct nwam_prop_table_entry ncu_prop_table_entries[] = {
81 {NWAM_NCU_PROP_TYPE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1, valid_type,
82 "specifies the NCU type - valid values are \'datalink\' and \'ip\'",
83 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
84 {NWAM_NCU_PROP_CLASS, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
85 valid_class,
86 "specifies the NCU class - valid values are "
87 "\'phys\' and \'ip\'",
88 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
89 {NWAM_NCU_PROP_PARENT_NCP, NWAM_VALUE_TYPE_STRING, B_FALSE, 1, 1,
90 valid_ncp,
91 "specifies the parent NCP name",
92 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
93 {NWAM_NCU_PROP_ACTIVATION_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
94 valid_ncu_activation_mode,
95 "specifies the NCU activation mode - valid values are:\n"
96 "\'prioritized\' and \'manual\'",
97 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
98 {NWAM_NCU_PROP_ENABLED, NWAM_VALUE_TYPE_BOOLEAN, B_TRUE, 0, 1,
99 nwam_valid_boolean,
100 "specifies if manual NCU is to be enabled",
101 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
102 {NWAM_NCU_PROP_PRIORITY_GROUP, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
103 nwam_valid_uint64,
104 "specifies the priority grouping of NCUs - lower values are "
105 "prioritized, negative values are invalid",
106 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
107 {NWAM_NCU_PROP_PRIORITY_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
108 valid_priority_mode,
109 "specifies the mode of prioritization - valid values are:\n"
110 "\'exclusive\', \'shared\' and \'all\'",
111 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
112 {NWAM_NCU_PROP_LINK_MAC_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
113 nwam_valid_mac_addr,
114 "specifies MAC address of form aa:bb:cc:dd:ee:ff for the link",
115 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
116 {NWAM_NCU_PROP_LINK_AUTOPUSH, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
117 NWAM_MAX_NUM_VALUES, valid_link_autopush,
118 "specifies modules to autopush on link",
119 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
120 {NWAM_NCU_PROP_LINK_MTU, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
121 valid_link_mtu,
122 "specifies MTU for link",
123 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
124 {NWAM_NCU_PROP_IP_VERSION, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
125 NWAM_MAX_NUM_VALUES, valid_ip_version,
126 "specifies IP versions for IP NCU - valid values are:\n"
127 "\'ipv4\' and \'ipv6\'",
128 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
129 {NWAM_NCU_PROP_IPV4_ADDRSRC, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
130 NWAM_MAX_NUM_VALUES, valid_addrsrc_v4,
131 "specifies IPv4 address source(s) - valid values are:\n"
132 "\'dhcp\' and \'static\'",
133 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
134 {NWAM_NCU_PROP_IPV4_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
135 NWAM_MAX_NUM_VALUES, nwam_valid_host_v4,
136 "specifies static IPv4 host address(es)",
137 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
138 {NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
139 1, nwam_valid_route_v4,
140 "specifies per-interface default IPv4 route",
141 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
142 {NWAM_NCU_PROP_IPV6_ADDRSRC, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
143 NWAM_MAX_NUM_VALUES, valid_addrsrc_v6,
144 "specifies IPv6 address source(s) - valid values are:\n"
145 "\'dhcp\', \'autoconf\' and \'static\'.\n"
146 "\'dhcp\' and \'autoconf\' are mandatory values.",
147 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
148 {NWAM_NCU_PROP_IPV6_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
149 NWAM_MAX_NUM_VALUES, nwam_valid_host_v6,
150 "specifies static IPv6 host address(es)",
151 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
152 {NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
153 1, nwam_valid_route_v6,
154 "specifies per-interface default IPv6 route",
155 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
156 {NWAM_NCU_PROP_IP_PRIMARY, NWAM_VALUE_TYPE_BOOLEAN, B_FALSE, 0,
157 1, nwam_valid_boolean,
158 "specifies the status of an interface as primary for the delivery"
159 " of client-wide configuration data",
160 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
161 {NWAM_NCU_PROP_IP_REQHOST, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
162 1, valid_reqhost,
163 "specifies a requested hostname for the interface",
164 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
167 #define NWAM_NUM_NCU_PROPS (sizeof (ncu_prop_table_entries) / \
168 sizeof (*ncu_prop_table_entries))
170 struct nwam_prop_table ncu_prop_table =
171 { NWAM_NUM_NCU_PROPS, ncu_prop_table_entries };
173 nwam_error_t
174 nwam_ncp_get_name(nwam_ncp_handle_t ncph, char **namep)
176 return (nwam_get_name(ncph, namep));
179 static nwam_error_t
180 nwam_ncp_name_to_file(const char *name, char **filename)
182 assert(name != NULL && filename != NULL);
184 if ((*filename = malloc(MAXPATHLEN)) == NULL)
185 return (NWAM_NO_MEMORY);
187 (void) snprintf(*filename, MAXPATHLEN, "%s%s%s%s", NWAM_CONF_DIR,
188 NWAM_NCP_CONF_FILE_PRE, name, NWAM_NCP_CONF_FILE_SUF);
190 return (NWAM_SUCCESS);
193 /* ARGSUSED1 */
194 nwam_error_t
195 nwam_ncp_create(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
197 nwam_error_t err;
198 char *ncpfile;
200 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, name, ncphp))
201 != NWAM_SUCCESS)
202 return (err);
204 /* Create empty container for NCUs */
205 if ((err = nwam_ncp_name_to_file(name, &ncpfile))
206 != NWAM_SUCCESS) {
207 nwam_free(*ncphp);
208 *ncphp = NULL;
209 return (err);
212 if ((err = nwam_commit(ncpfile, *ncphp, flags)) != NWAM_SUCCESS) {
213 nwam_free(*ncphp);
214 *ncphp = NULL;
217 free(ncpfile);
219 return (err);
222 /* Used by libnwam_files.c */
223 nwam_error_t
224 nwam_ncp_file_to_name(const char *path, char **name)
226 char path_copy[MAXPATHLEN];
227 char *filename, *suffix;
229 assert(path != NULL && name != NULL);
231 /* Make a copy as basename(3c) may modify string */
232 (void) strlcpy(path_copy, path, MAXPATHLEN);
234 if ((*name = malloc(NWAM_MAX_NAME_LEN)) == NULL)
235 return (NWAM_NO_MEMORY);
237 if ((filename = basename(path_copy)) == NULL) {
238 free(*name);
239 return (NWAM_ENTITY_INVALID);
242 /* Ensure filename begins/ends with right prefix/suffix */
243 if (sscanf(filename, NWAM_NCP_CONF_FILE_PRE "%256[^\n]s", *name) < 1) {
244 free(*name);
245 return (NWAM_ENTITY_INVALID);
247 suffix = *name + strlen(*name) - strlen(NWAM_NCP_CONF_FILE_SUF);
248 if (strstr(*name, NWAM_NCP_CONF_FILE_SUF) != suffix) {
249 free(*name);
250 return (NWAM_ENTITY_INVALID);
252 suffix[0] = '\0';
254 return (NWAM_SUCCESS);
257 /* ARGSUSED1 */
258 nwam_error_t
259 nwam_ncp_read(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
261 char *filename;
262 nwam_error_t err;
264 assert(name != NULL && ncphp != NULL);
266 /* try to read the associated ncp configuration */
267 if ((err = nwam_ncp_name_to_file(name, &filename)) != NWAM_SUCCESS) {
268 *ncphp = NULL;
269 return (err);
272 err = nwam_read(NWAM_OBJECT_TYPE_NCP, filename, name, flags, ncphp);
273 free(filename);
274 return (err);
277 static nwam_error_t
278 nwam_ncu_get_parent_ncp_name(nwam_ncu_handle_t ncuh, char **parentnamep)
280 nwam_value_t parentval = NULL;
281 char *parentname;
282 nwam_error_t err;
284 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_PARENT_NCP,
285 &parentval)) != NWAM_SUCCESS ||
286 (err = nwam_value_get_string(parentval, &parentname))
287 != NWAM_SUCCESS ||
288 (*parentnamep = strdup(parentname)) == NULL) {
289 if (parentval != NULL)
290 nwam_value_free(parentval);
291 *parentnamep = NULL;
292 return (err);
294 nwam_value_free(parentval);
296 return (NWAM_SUCCESS);
299 static int
300 nwam_ncp_copy_callback(nwam_ncu_handle_t oldncuh, void *arg)
302 nwam_error_t err;
303 nwam_ncu_handle_t newncuh = NULL;
304 char *oldparent;
305 char *oldfilename = NULL, *newfilename = NULL;
306 nwam_ncp_handle_t newncph = (nwam_ncp_handle_t)arg;
307 nwam_value_t newparentval;
309 /* Get filenames for the new and old NCU's */
310 if ((err = nwam_ncu_get_parent_ncp_name(oldncuh, &oldparent))
311 != NWAM_SUCCESS)
312 return (err);
313 err = nwam_ncp_name_to_file(oldparent, &oldfilename);
314 free(oldparent);
315 if (err != NWAM_SUCCESS)
316 return (err);
317 if ((err = nwam_ncp_name_to_file(newncph->nwh_name, &newfilename))
318 != NWAM_SUCCESS)
319 goto fail;
321 /* new NCU name (and typedname) is the same as the old name */
322 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, oldncuh->nwh_name,
323 &newncuh)) != NWAM_SUCCESS)
324 goto fail;
325 /* Duplicate the old NCU's data */
326 if ((err = nwam_dup_object_list(oldncuh->nwh_data,
327 &(newncuh->nwh_data))) != NWAM_SUCCESS)
328 goto fail;
330 /* Update the parent property for the new NCU */
331 if ((err = nwam_value_create_string(newncph->nwh_name, &newparentval))
332 != NWAM_SUCCESS)
333 goto fail;
334 err = nwam_set_prop_value(newncuh->nwh_data, NWAM_NCU_PROP_PARENT_NCP,
335 newparentval);
336 nwam_value_free(newparentval);
337 if (err != NWAM_SUCCESS)
338 goto fail;
340 /* Save the new NCU */
341 err = nwam_commit(newfilename, newncuh, 0);
343 fail:
344 free(oldfilename);
345 free(newfilename);
346 nwam_ncu_free(newncuh);
347 return (err);
350 nwam_error_t
351 nwam_ncp_copy(nwam_ncp_handle_t oldncph, const char *newname,
352 nwam_ncp_handle_t *newncphp)
354 nwam_ncp_handle_t ncph;
355 nwam_error_t err;
356 int cb_ret;
358 assert(oldncph != NULL && newname != NULL && newncphp != NULL);
360 /* check if newname NCP already exists */
361 if (nwam_ncp_read(newname, 0, &ncph) == NWAM_SUCCESS) {
362 nwam_ncp_free(ncph);
363 *newncphp = NULL;
364 return (NWAM_ENTITY_EXISTS);
367 /* create new handle */
368 if ((err = nwam_ncp_create(newname, 0, newncphp)) != NWAM_SUCCESS)
369 return (err);
371 err = nwam_ncp_walk_ncus(oldncph, nwam_ncp_copy_callback, *newncphp,
372 NWAM_FLAG_NCU_TYPE_CLASS_ALL, &cb_ret);
373 if (err != NWAM_SUCCESS) {
374 /* remove the NCP even if any NCU's had already been copied */
375 (void) nwam_ncp_destroy(*newncphp, 0);
376 *newncphp = NULL;
377 if (err == NWAM_WALK_HALTED)
378 return (cb_ret);
379 else
380 return (err);
383 return (NWAM_SUCCESS);
387 * Convert type to flag
389 static uint64_t
390 nwam_ncu_type_to_flag(nwam_ncu_type_t type)
392 switch (type) {
393 case NWAM_NCU_TYPE_LINK:
394 return (NWAM_FLAG_NCU_TYPE_LINK);
395 case NWAM_NCU_TYPE_INTERFACE:
396 return (NWAM_FLAG_NCU_TYPE_INTERFACE);
397 case NWAM_NCU_TYPE_ANY:
398 return (NWAM_FLAG_NCU_TYPE_ALL);
399 default:
400 return (0);
405 * Convert class to flag
407 uint64_t
408 nwam_ncu_class_to_flag(nwam_ncu_class_t class)
410 switch (class) {
411 case NWAM_NCU_CLASS_PHYS:
412 return (NWAM_FLAG_NCU_CLASS_PHYS);
413 case NWAM_NCU_CLASS_IP:
414 return (NWAM_FLAG_NCU_CLASS_IP);
415 case NWAM_NCU_CLASS_ANY:
416 return (NWAM_FLAG_NCU_CLASS_ALL);
417 default:
418 return (0);
423 * Infer NCU type from NCU class
425 nwam_ncu_type_t
426 nwam_ncu_class_to_type(nwam_ncu_class_t class)
428 switch (class) {
429 case NWAM_NCU_CLASS_PHYS:
430 return (NWAM_NCU_TYPE_LINK);
431 case NWAM_NCU_CLASS_IP:
432 return (NWAM_NCU_TYPE_INTERFACE);
433 case NWAM_NCU_CLASS_ANY:
434 return (NWAM_NCU_TYPE_ANY);
435 default:
436 return (NWAM_NCU_TYPE_UNKNOWN);
441 * Make ncp active, deactivating any other active ncp.
443 nwam_error_t
444 nwam_ncp_enable(nwam_ncp_handle_t ncph)
446 nwam_error_t err;
447 char *name;
449 assert(ncph != NULL);
451 err = nwam_enable(NULL, ncph);
453 if (err == NWAM_ERROR_BIND) {
455 * nwamd is not running, set active_ncp property so when
456 * nwamd is next started, this NCP will be used.
458 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
459 return (err);
461 err = nwam_set_smf_string_property(NWAM_FMRI, NWAM_PG,
462 NWAM_PROP_ACTIVE_NCP, name);
463 free(name);
466 return (err);
469 /* Compare NCP names c1 and c2 using strcasecmp() */
470 static int
471 ncpname_cmp(const void *c1, const void *c2)
473 return (strcasecmp(*(const char **)c1, *(const char **)c2));
476 /* ARGSUSED1 */
477 nwam_error_t
478 nwam_walk_ncps(int (*cb)(nwam_ncp_handle_t, void *), void *data,
479 uint64_t flags, int *retp)
481 char *ncpname, **ncpfiles;
482 nwam_ncp_handle_t ncph;
483 nwam_error_t err;
484 nwam_value_t value;
485 void *objlist;
486 uint_t i, num_ncpfiles;
487 int ret = 0;
489 assert(cb != NULL);
491 if ((err = nwam_valid_flags(flags, NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
492 return (err);
494 * To get list of NCP files, call nwam_read_object_from_backend()
495 * with "parent" argument set to NULL. We get back an object list
496 * consisting of string arrays for each object type - NCP, ENM
497 * and location. We retrieve the NCP list, which corresponds to
498 * the set of NCP backend parent objects (these are files at present).
500 if ((err = nwam_read_object_from_backend(NULL, NULL, flags,
501 &objlist)) != NWAM_SUCCESS)
502 return (err);
504 if ((err = nwam_get_prop_value(objlist, NWAM_NCP_OBJECT_STRING, &value))
505 != NWAM_SUCCESS) {
506 nwam_free_object_list(objlist);
507 return (err);
509 if ((err = nwam_value_get_string_array(value, &ncpfiles,
510 &num_ncpfiles)) != NWAM_SUCCESS) {
511 nwam_value_free(value);
512 nwam_free_object_list(objlist);
513 return (err);
516 /* sort the NCP names alphabetically */
517 qsort(ncpfiles, num_ncpfiles, sizeof (char *), ncpname_cmp);
519 for (i = 0; i < num_ncpfiles; i++) {
520 if (nwam_ncp_file_to_name(ncpfiles[i], &ncpname)
521 != NWAM_SUCCESS)
522 continue;
523 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, ncpname,
524 &ncph)) != NWAM_SUCCESS) {
525 free(ncpname);
526 break;
528 ret = cb(ncph, data);
529 free(ncph);
530 free(ncpname);
531 if (ret != 0) {
532 err = NWAM_WALK_HALTED;
533 break;
536 nwam_value_free(value);
537 nwam_free_object_list(objlist);
539 if (retp != NULL)
540 *retp = ret;
541 return (err);
545 * Checks if NCP is read-only. Only NWAM_NCP_NAME_AUTOMATIC is read-only
546 * for all but the netadm user (which nwamd runs as).
548 nwam_error_t
549 nwam_ncp_get_read_only(nwam_ncp_handle_t ncph, boolean_t *readp)
551 nwam_error_t err;
552 char *name;
554 assert(ncph != NULL && readp != NULL);
556 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
557 return (err);
559 if (NWAM_NCP_AUTOMATIC(name))
560 *readp = !nwam_uid_is_special();
561 else
562 *readp = B_FALSE;
564 free(name);
565 return (NWAM_SUCCESS);
568 /* Checks if NCU is writable depending on its parent */
569 nwam_error_t
570 nwam_ncu_get_read_only(nwam_ncu_handle_t ncuh, boolean_t *readp)
572 nwam_error_t err;
573 nwam_ncp_handle_t ncph;
575 assert(ncuh != NULL && readp != NULL);
577 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
578 return (err);
580 err = nwam_ncp_get_read_only(ncph, readp);
581 nwam_ncp_free(ncph);
582 return (err);
585 /* Returns true if the NCP is active */
586 static boolean_t
587 nwam_ncp_is_active(nwam_ncp_handle_t ncph)
589 char *active_ncp, *name;
590 boolean_t ret;
592 assert(ncph != NULL);
595 * Determine which NCP is active via the nwamd/active_ncp property
596 * value. This allows us to determine which NCP is active even
597 * if nwamd is not running.
599 if (nwam_ncp_get_name(ncph, &name) != NWAM_SUCCESS ||
600 nwam_get_smf_string_property(NWAM_FMRI, NWAM_PG,
601 NWAM_PROP_ACTIVE_NCP, &active_ncp) != NWAM_SUCCESS)
602 return (B_FALSE);
604 ret = (strcmp(name, active_ncp) == 0);
606 free(active_ncp);
607 free(name);
609 return (ret);
612 nwam_error_t
613 nwam_ncp_destroy(nwam_ncp_handle_t ncph, uint64_t flags)
615 char *filename;
616 nwam_error_t err;
617 boolean_t read_only;
619 assert(ncph != NULL);
621 if ((err = nwam_ncp_get_read_only(ncph, &read_only)) != NWAM_SUCCESS)
622 return (err);
623 if (read_only)
624 return (NWAM_ENTITY_NOT_DESTROYABLE);
626 if (nwam_ncp_is_active(ncph))
627 return (NWAM_ENTITY_IN_USE);
629 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &filename))
630 != NWAM_SUCCESS)
631 return (err);
633 err = nwam_destroy(filename, ncph, flags);
634 free(filename);
636 return (NWAM_SUCCESS);
639 static nwam_error_t
640 nwam_ncu_internal_name_to_name(const char *internalname,
641 nwam_ncu_type_t *typep, char **namep)
643 char *prefixstr;
645 assert(internalname != NULL && namep != NULL);
647 if (strncasecmp(internalname, NWAM_NCU_LINK_NAME_PRE,
648 strlen(NWAM_NCU_LINK_NAME_PRE)) == 0) {
649 prefixstr = NWAM_NCU_LINK_NAME_PRE;
650 *typep = NWAM_NCU_TYPE_LINK;
651 } else if (strncasecmp(internalname, NWAM_NCU_INTERFACE_NAME_PRE,
652 strlen(NWAM_NCU_INTERFACE_NAME_PRE)) == 0) {
653 prefixstr = NWAM_NCU_INTERFACE_NAME_PRE;
654 *typep = NWAM_NCU_TYPE_INTERFACE;
655 } else {
656 return (NWAM_INVALID_ARG);
659 *namep = strdup(internalname + strlen(prefixstr));
660 if (*namep == NULL)
661 return (NWAM_NO_MEMORY);
662 return (NWAM_SUCCESS);
665 /* ARGSUSED2 */
666 static int
667 ncu_selectcb(struct nwam_handle *hp, uint64_t flags, void *data)
669 nwam_ncu_handle_t ncuh = hp;
670 nwam_value_t typeval = NULL, classval = NULL;
671 uint64_t type, class, matchflags, walkfilter;
673 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval)
674 != NWAM_SUCCESS ||
675 nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS, &classval)
676 != NWAM_SUCCESS) {
677 if (typeval != NULL)
678 nwam_value_free(typeval);
679 return (NWAM_INVALID_ARG);
681 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS ||
682 nwam_value_get_uint64(classval, &class) != NWAM_SUCCESS) {
683 nwam_value_free(typeval);
684 nwam_value_free(classval);
685 return (NWAM_INVALID_ARG);
688 matchflags = nwam_ncu_type_to_flag(type) |
689 nwam_ncu_class_to_flag(class);
690 nwam_value_free(typeval);
691 nwam_value_free(classval);
693 if ((walkfilter = (flags & NWAM_WALK_FILTER_MASK)) == 0)
694 walkfilter = NWAM_FLAG_NCU_TYPE_CLASS_ALL;
696 if (matchflags & walkfilter)
697 return (NWAM_SUCCESS);
698 return (NWAM_INVALID_ARG);
701 nwam_error_t
702 nwam_ncp_walk_ncus(nwam_ncp_handle_t ncph,
703 int(*cb)(nwam_ncu_handle_t, void *), void *data, uint64_t flags, int *retp)
705 char *ncpfile;
706 nwam_error_t err;
708 assert(ncph != NULL && cb != NULL);
710 if ((err = nwam_valid_flags(flags,
711 NWAM_FLAG_NCU_TYPE_CLASS_ALL | NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
712 return (err);
714 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
715 != NWAM_SUCCESS)
716 return (err);
718 err = nwam_walk(NWAM_OBJECT_TYPE_NCU, ncpfile, cb, data, flags,
719 retp, ncu_selectcb);
720 free(ncpfile);
722 return (err);
725 void
726 nwam_ncp_free(nwam_ncp_handle_t ncph)
728 nwam_free(ncph);
732 * Are ncu type and class compatible?
734 static boolean_t
735 nwam_ncu_type_class_compatible(nwam_ncu_type_t type, nwam_ncu_class_t class)
737 switch (type) {
738 case NWAM_NCU_TYPE_LINK:
739 return (class == NWAM_NCU_CLASS_PHYS);
740 case NWAM_NCU_TYPE_INTERFACE:
741 return (class == NWAM_NCU_CLASS_IP);
742 default:
743 return (B_FALSE);
747 /* Name to validate may be internal name. If so, convert it before validating */
748 static boolean_t
749 valid_ncu_name(const char *name)
751 char *n;
752 boolean_t ret;
753 nwam_ncu_type_t type;
755 if (nwam_ncu_internal_name_to_name(name, &type, &n) == NWAM_SUCCESS) {
757 ret = dladm_valid_linkname(n);
758 free(n);
759 } else {
760 ret = dladm_valid_linkname(name);
763 return (ret);
766 nwam_error_t
767 nwam_ncu_create(nwam_ncp_handle_t ncph, const char *name,
768 nwam_ncu_type_t type, nwam_ncu_class_t class, nwam_ncu_handle_t *ncuhp)
770 nwam_ncu_handle_t ncuh;
771 nwam_value_t typeval = NULL, classval = NULL, parentval = NULL;
772 nwam_value_t enabledval = NULL;
773 nwam_error_t err;
774 boolean_t read_only;
775 char *typedname;
777 assert(ncph != NULL && name != NULL && ncuhp != NULL);
779 if (!valid_ncu_name(name))
780 return (NWAM_INVALID_ARG);
782 if ((err = nwam_ncp_get_read_only(ncph, &read_only)) != NWAM_SUCCESS)
783 return (err);
784 if (read_only)
785 return (NWAM_ENTITY_READ_ONLY);
787 if (nwam_ncu_read(ncph, name, type, 0, &ncuh) == NWAM_SUCCESS) {
788 nwam_ncu_free(ncuh);
789 return (NWAM_ENTITY_EXISTS);
792 if (!valid_ncu_name(name) ||
793 !nwam_ncu_type_class_compatible(type, class))
794 return (NWAM_INVALID_ARG);
796 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname))
797 != NWAM_SUCCESS)
798 return (err);
800 /* Create handle */
801 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, typedname, ncuhp))
802 != NWAM_SUCCESS)
803 return (err);
804 free(typedname);
807 * Create new object list for NCU. The new NCU is initialized with
808 * the appropriate type and class.
810 if ((err = nwam_alloc_object_list(&(*ncuhp)->nwh_data)) != NWAM_SUCCESS)
811 goto finish;
813 if ((err = nwam_value_create_uint64(type, &typeval))
814 != NWAM_SUCCESS ||
815 (err = nwam_value_create_uint64(class, &classval))
816 != NWAM_SUCCESS ||
817 (err = nwam_value_create_string(ncph->nwh_name, &parentval))
818 != NWAM_SUCCESS ||
819 (err = nwam_value_create_boolean(B_TRUE, &enabledval))
820 != NWAM_SUCCESS) {
821 goto finish;
823 if ((err = nwam_set_prop_value((*ncuhp)->nwh_data, NWAM_NCU_PROP_TYPE,
824 typeval)) != NWAM_SUCCESS ||
825 (err = nwam_set_prop_value((*ncuhp)->nwh_data, NWAM_NCU_PROP_CLASS,
826 classval)) != NWAM_SUCCESS ||
827 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
828 NWAM_NCU_PROP_PARENT_NCP, parentval)) != NWAM_SUCCESS ||
829 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
830 NWAM_NCU_PROP_ENABLED, enabledval)) != NWAM_SUCCESS) {
831 goto finish;
834 /* Set default IP, datalink properties */
835 if (type == NWAM_NCU_TYPE_INTERFACE && class == NWAM_NCU_CLASS_IP) {
837 uint64_t ver[] = { IPV4_VERSION, IPV6_VERSION };
838 uint64_t v6src[] = { NWAM_ADDRSRC_DHCP, NWAM_ADDRSRC_AUTOCONF };
839 uint_t vercnt = 2, v6srccnt = 2;
840 nwam_value_t ipver = NULL, v4addrsrc = NULL, v6addrsrc = NULL;
842 if ((err = nwam_value_create_uint64_array(ver, vercnt, &ipver))
843 != NWAM_SUCCESS ||
844 (err = nwam_value_create_uint64(NWAM_ADDRSRC_DHCP,
845 &v4addrsrc)) != NWAM_SUCCESS ||
846 (err = nwam_value_create_uint64_array(v6src, v6srccnt,
847 &v6addrsrc)) != NWAM_SUCCESS) {
848 nwam_value_free(ipver);
849 nwam_value_free(v4addrsrc);
850 goto finish;
852 if ((err = nwam_set_prop_value((*ncuhp)->nwh_data,
853 NWAM_NCU_PROP_IP_VERSION, ipver)) == NWAM_SUCCESS &&
854 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
855 NWAM_NCU_PROP_IPV4_ADDRSRC, v4addrsrc)) == NWAM_SUCCESS) {
856 err = nwam_set_prop_value((*ncuhp)->nwh_data,
857 NWAM_NCU_PROP_IPV6_ADDRSRC, v6addrsrc);
859 nwam_value_free(ipver);
860 nwam_value_free(v4addrsrc);
861 nwam_value_free(v6addrsrc);
862 } else {
863 nwam_value_t actval = NULL;
864 if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL,
865 &actval)) != NWAM_SUCCESS)
866 goto finish;
867 err = nwam_set_prop_value((*ncuhp)->nwh_data,
868 NWAM_NCU_PROP_ACTIVATION_MODE, actval);
869 nwam_value_free(actval);
872 finish:
873 nwam_value_free(typeval);
874 nwam_value_free(classval);
875 nwam_value_free(parentval);
876 nwam_value_free(enabledval);
877 if (err != NWAM_SUCCESS) {
878 nwam_ncu_free(*ncuhp);
879 *ncuhp = NULL;
881 return (err);
884 nwam_error_t
885 nwam_ncu_read(nwam_ncp_handle_t ncph, const char *name,
886 nwam_ncu_type_t type, uint64_t flags, nwam_ncu_handle_t *ncuhp)
888 char *ncpfile, *typedname;
889 nwam_error_t err, err_ip, err_link;
890 nwam_ncu_handle_t ncuh_ip, ncuh_link;
892 assert(ncph != NULL && name != NULL && ncuhp != NULL);
894 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
895 != NWAM_SUCCESS)
896 return (err);
898 if (type == NWAM_NCU_TYPE_ANY) {
900 free(ncpfile);
903 * If we get to this point, we have discovered that no
904 * NCU type is discernable from name or type arguments.
905 * Either exactly one NCU called name must exist of either
906 * type, or the operation should fail.
908 err_ip = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_INTERFACE,
909 flags, &ncuh_ip);
910 err_link = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK,
911 flags, &ncuh_link);
913 *ncuhp = NULL;
915 if (err_ip == NWAM_SUCCESS && err_link == NWAM_SUCCESS) {
916 nwam_ncu_free(ncuh_ip);
917 nwam_ncu_free(ncuh_link);
918 err = NWAM_ENTITY_MULTIPLE_VALUES;
919 } else if (err_ip != NWAM_SUCCESS && err_link != NWAM_SUCCESS) {
920 err = NWAM_ENTITY_NOT_FOUND;
921 } else {
922 if (err_ip == NWAM_SUCCESS) {
923 *ncuhp = ncuh_ip;
924 } else {
925 *ncuhp = ncuh_link;
927 err = NWAM_SUCCESS;
930 return (err);
932 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname)) !=
933 NWAM_SUCCESS) {
934 free(ncpfile);
935 return (err);
937 err = nwam_read(NWAM_OBJECT_TYPE_NCU, ncpfile, typedname, flags, ncuhp);
939 free(typedname);
940 free(ncpfile);
942 return (err);
945 nwam_error_t
946 nwam_ncu_get_name(nwam_ncu_handle_t ncuh, char **namep)
948 nwam_ncu_type_t type;
950 assert(ncuh != NULL && namep != NULL);
952 return (nwam_ncu_internal_name_to_name(ncuh->nwh_name, &type, namep));
955 nwam_error_t
956 nwam_ncu_name_to_typed_name(const char *name, nwam_ncu_type_t type,
957 char **typednamep)
959 char *prefixstr;
960 size_t typednamesz;
962 assert(name != NULL && typednamep != NULL);
964 switch (type) {
965 case NWAM_NCU_TYPE_INTERFACE:
966 prefixstr = NWAM_NCU_INTERFACE_NAME_PRE;
967 break;
968 case NWAM_NCU_TYPE_LINK:
969 prefixstr = NWAM_NCU_LINK_NAME_PRE;
970 break;
971 default:
972 return (NWAM_INVALID_ARG);
974 typednamesz = strlen(name) + strlen(prefixstr) + 1;
975 if ((*typednamep = malloc(typednamesz)) == NULL)
976 return (NWAM_NO_MEMORY);
978 /* Name may be already qualified by type */
979 if (strncasecmp(prefixstr, name, strlen(prefixstr)) == 0) {
980 (void) snprintf(*typednamep, typednamesz, "%s", name);
981 } else {
982 (void) snprintf(*typednamep, typednamesz, "%s%s",
983 prefixstr, name);
986 return (NWAM_SUCCESS);
989 nwam_error_t
990 nwam_ncu_typed_name_to_name(const char *typed_name, nwam_ncu_type_t *typep,
991 char **name)
993 return (nwam_ncu_internal_name_to_name(typed_name, typep, name));
996 void
997 nwam_ncu_free(nwam_ncu_handle_t ncuh)
999 nwam_free(ncuh);
1002 nwam_error_t
1003 nwam_ncu_copy(nwam_ncu_handle_t oldncuh, const char *newname,
1004 nwam_ncu_handle_t *newncuhp)
1006 nwam_ncp_handle_t ncph;
1007 nwam_ncu_handle_t ncuh;
1008 nwam_error_t err;
1009 nwam_value_t typeval;
1010 uint64_t type;
1011 char *typednewname;
1013 assert(oldncuh != NULL && newname != NULL && newncuhp != NULL);
1015 if (nwam_ncu_get_prop_value(oldncuh, NWAM_NCU_PROP_TYPE,
1016 &typeval) != NWAM_SUCCESS) {
1017 return (NWAM_INVALID_ARG);
1019 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1020 nwam_value_free(typeval);
1021 return (NWAM_INVALID_ARG);
1023 nwam_value_free(typeval);
1025 /* check if newname NCU already exists */
1026 if ((err = nwam_ncu_get_ncp(oldncuh, &ncph)) != NWAM_SUCCESS)
1027 return (err);
1028 if (nwam_ncu_read(ncph, newname, type, 0, &ncuh) == NWAM_SUCCESS) {
1029 nwam_ncu_free(ncuh);
1030 nwam_ncp_free(ncph);
1031 return (NWAM_ENTITY_EXISTS);
1033 nwam_ncp_free(ncph);
1035 if ((err = nwam_ncu_name_to_typed_name(newname, type, &typednewname))
1036 != NWAM_SUCCESS)
1037 return (err);
1039 err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, typednewname, newncuhp);
1040 free(typednewname);
1041 if (err != NWAM_SUCCESS)
1042 return (err);
1043 if ((err = nwam_dup_object_list(oldncuh->nwh_data,
1044 &((*newncuhp)->nwh_data))) != NWAM_SUCCESS) {
1045 free(*newncuhp);
1046 *newncuhp = NULL;
1047 return (err);
1050 return (NWAM_SUCCESS);
1053 nwam_error_t
1054 nwam_ncu_delete_prop(nwam_ncu_handle_t ncuh, const char *propname)
1056 boolean_t ro_ncu, ro_prop;
1057 nwam_error_t err;
1058 void *olddata;
1060 assert(ncuh != NULL && propname != NULL);
1062 if ((err = nwam_ncu_get_read_only(ncuh, &ro_ncu)) != NWAM_SUCCESS ||
1063 (err = nwam_ncu_prop_read_only(propname, &ro_prop)) != NWAM_SUCCESS)
1064 return (err);
1065 if (ro_ncu || ro_prop)
1066 return (NWAM_ENTITY_READ_ONLY);
1069 * Duplicate data, remove property and validate. If validation
1070 * fails, revert to data duplicated prior to remove.
1072 if ((err = nwam_dup_object_list(ncuh->nwh_data, &olddata))
1073 != NWAM_SUCCESS)
1074 return (err);
1075 if ((err = nwam_delete_prop(ncuh->nwh_data, propname))
1076 != NWAM_SUCCESS) {
1077 nwam_free_object_list(ncuh->nwh_data);
1078 ncuh->nwh_data = olddata;
1079 return (err);
1081 if ((err = nwam_ncu_validate(ncuh, NULL)) != NWAM_SUCCESS) {
1082 nwam_free_object_list(ncuh->nwh_data);
1083 ncuh->nwh_data = olddata;
1084 return (err);
1086 nwam_free_object_list(olddata);
1088 return (NWAM_SUCCESS);
1091 nwam_error_t
1092 nwam_ncu_set_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1093 nwam_value_t value)
1095 boolean_t ro_ncu, ro_prop;
1096 nwam_error_t err;
1097 nwam_ncp_handle_t ncph;
1099 assert(ncuh != NULL && propname != NULL && value != NULL);
1101 if ((err = nwam_ncu_get_read_only(ncuh, &ro_ncu)) != NWAM_SUCCESS ||
1102 (err = nwam_ncu_prop_read_only(propname, &ro_prop)) != NWAM_SUCCESS)
1103 return (err);
1104 if (ro_ncu || ro_prop)
1105 return (NWAM_ENTITY_READ_ONLY);
1107 err = nwam_ncu_get_ncp(ncuh, &ncph);
1108 if (err != NWAM_SUCCESS && err != NWAM_INVALID_ARG) {
1110 * If "parent" property doesn't exist, NWAM_INVALID_ARG
1111 * is returned. Allow the setting to continue.
1113 return (err);
1115 nwam_ncp_free(ncph);
1117 /* Need to ensure property, type and value are valid */
1118 if ((err = nwam_ncu_validate_prop(ncuh, propname, value))
1119 != NWAM_SUCCESS)
1120 return (err);
1122 return (nwam_set_prop_value(ncuh->nwh_data, propname, value));
1125 nwam_error_t
1126 nwam_ncu_get_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1127 nwam_value_t *valuep)
1129 assert(ncuh != NULL && propname != NULL && valuep != NULL);
1131 return (nwam_get_prop_value(ncuh->nwh_data, propname, valuep));
1134 nwam_error_t
1135 nwam_ncu_walk_props(nwam_ncu_handle_t ncuh,
1136 int (*cb)(const char *, nwam_value_t, void *),
1137 void *data, uint64_t flags, int *retp)
1139 return (nwam_walk_props(ncuh, cb, data, flags, retp));
1142 nwam_error_t
1143 nwam_ncu_get_ncp(nwam_ncu_handle_t ncuh, nwam_ncp_handle_t *ncphp)
1145 nwam_error_t err;
1146 char *parentname = NULL;
1148 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &parentname))
1149 != NWAM_SUCCESS ||
1150 (err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, parentname, ncphp))
1151 != NWAM_SUCCESS) {
1152 free(parentname);
1153 return (err);
1155 free(parentname);
1157 return (NWAM_SUCCESS);
1160 nwam_error_t
1161 nwam_ncu_commit(nwam_ncu_handle_t ncuh, uint64_t flags)
1163 nwam_error_t err;
1164 boolean_t read_only;
1165 char *ncpfile, *ncpname;
1167 assert(ncuh != NULL && ncuh->nwh_data != NULL);
1169 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1170 return (err);
1171 if (read_only)
1172 return (NWAM_ENTITY_READ_ONLY);
1174 if ((err = nwam_ncu_validate(ncuh, NULL)) != NWAM_SUCCESS ||
1175 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1176 != NWAM_SUCCESS)
1177 return (err);
1179 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile)) != NWAM_SUCCESS) {
1180 free(ncpname);
1181 return (err);
1184 err = nwam_commit(ncpfile, ncuh, flags);
1186 free(ncpname);
1187 free(ncpfile);
1189 return (err);
1191 /* Get the NCU type */
1192 nwam_error_t
1193 nwam_ncu_get_ncu_type(nwam_ncu_handle_t ncuh, nwam_ncu_type_t *typep)
1195 nwam_error_t err;
1196 nwam_value_t typeval;
1197 uint64_t type;
1199 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval))
1200 != NWAM_SUCCESS)
1201 return (err);
1202 err = nwam_value_get_uint64(typeval, &type);
1203 nwam_value_free(typeval);
1204 if (err != NWAM_SUCCESS)
1205 return (err);
1207 *typep = type;
1208 return (NWAM_SUCCESS);
1211 /* Get the NCU class */
1212 nwam_error_t
1213 nwam_ncu_get_ncu_class(nwam_ncu_handle_t ncuh, nwam_ncu_class_t *classp)
1215 nwam_error_t err;
1216 nwam_value_t classval;
1217 uint64_t class;
1219 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS,
1220 &classval)) != NWAM_SUCCESS)
1221 return (err);
1222 err = nwam_value_get_uint64(classval, &class);
1223 nwam_value_free(classval);
1224 if (err != NWAM_SUCCESS)
1225 return (err);
1227 *classp = class;
1228 return (NWAM_SUCCESS);
1232 * Determine if the NCU has manual activation-mode or not.
1234 nwam_error_t
1235 nwam_ncu_is_manual(nwam_ncu_handle_t ncuh, boolean_t *manualp)
1237 nwam_error_t err;
1238 nwam_value_t actval;
1239 uint64_t activation;
1241 assert(ncuh != NULL);
1243 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ACTIVATION_MODE,
1244 &actval)) != NWAM_SUCCESS)
1245 return (err);
1246 err = nwam_value_get_uint64(actval, &activation);
1247 nwam_value_free(actval);
1248 if (err != NWAM_SUCCESS)
1249 return (err);
1251 if (activation == NWAM_ACTIVATION_MODE_MANUAL)
1252 *manualp = B_TRUE;
1253 else
1254 *manualp = B_FALSE;
1255 return (NWAM_SUCCESS);
1258 /* Determine if NCU is enabled or not */
1259 static nwam_error_t
1260 nwam_ncu_is_enabled(nwam_ncu_handle_t ncuh, boolean_t *enabledp)
1262 nwam_error_t err;
1263 nwam_value_t enabledval;
1265 assert(ncuh != NULL);
1267 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED,
1268 &enabledval)) != NWAM_SUCCESS)
1269 return (err);
1270 err = nwam_value_get_boolean(enabledval, enabledp);
1271 nwam_value_free(enabledval);
1272 return (err);
1275 /* Update the enabled property */
1276 static nwam_error_t
1277 nwam_ncu_update_enabled(nwam_ncu_handle_t ncuh, boolean_t enabled)
1279 nwam_error_t err;
1280 nwam_value_t enabledval;
1282 if ((err = nwam_value_create_boolean(enabled, &enabledval))
1283 != NWAM_SUCCESS)
1284 return (err);
1285 err = nwam_set_prop_value(ncuh->nwh_data, NWAM_NCU_PROP_ENABLED,
1286 enabledval);
1287 nwam_value_free(enabledval);
1288 if (err != NWAM_SUCCESS)
1289 return (err);
1290 return (nwam_ncu_commit(ncuh, NWAM_FLAG_ENTITY_ENABLE));
1294 * Make ncu active; fails if the NCU's parent NCP is not active.
1296 nwam_error_t
1297 nwam_ncu_enable(nwam_ncu_handle_t ncuh)
1299 char *ncpname = NULL;
1300 nwam_error_t err;
1301 nwam_ncu_type_t type;
1302 boolean_t read_only, enabled, manual;
1304 assert(ncuh != NULL);
1306 /* Don't allow NCUs of Automatic NCP to be enabled */
1307 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1308 return (err);
1309 if (read_only)
1310 return (NWAM_ENTITY_NOT_MANUAL);
1312 /* Link NCUs with manual activation-mode or IP NCUs can be enabled */
1313 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1314 return (err);
1316 if (type == NWAM_NCU_TYPE_LINK) {
1317 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1318 return (err);
1319 if (!manual)
1320 return (NWAM_ENTITY_NOT_MANUAL);
1323 /* Make sure NCU is not enabled */
1324 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1325 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1326 != NWAM_SUCCESS)
1327 return (err);
1329 if (enabled) {
1330 free(ncpname);
1331 return (NWAM_SUCCESS);
1334 if ((err = nwam_ncu_update_enabled(ncuh, B_TRUE)) != NWAM_SUCCESS) {
1335 free(ncpname);
1336 return (err);
1339 err = nwam_enable(ncpname, ncuh);
1340 free(ncpname);
1342 /* nwamd may not be running, that's okay. */
1343 if (err == NWAM_ERROR_BIND)
1344 return (NWAM_SUCCESS);
1345 else
1346 return (err);
1350 * Disable ncu; fails if the NCU's parent NCP is not active, or if the
1351 * NCU is not currently active.
1353 nwam_error_t
1354 nwam_ncu_disable(nwam_ncu_handle_t ncuh)
1356 char *ncpname = NULL;
1357 nwam_error_t err;
1358 nwam_ncu_type_t type;
1359 boolean_t read_only, enabled, manual;
1361 assert(ncuh != NULL);
1363 /* Don't allow NCUs of Automatic NCP to be disabled */
1364 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1365 return (err);
1366 if (read_only)
1367 return (NWAM_ENTITY_NOT_MANUAL);
1369 /* Link NCUs with manual activation-mode or IP NCUs can be disabled */
1370 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1371 return (err);
1373 if (type == NWAM_NCU_TYPE_LINK) {
1374 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1375 return (err);
1376 if (!manual)
1377 return (NWAM_ENTITY_NOT_MANUAL);
1380 /* Make sure NCU is enabled */
1381 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1382 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1383 != NWAM_SUCCESS)
1384 return (err);
1386 if (!enabled) {
1387 free(ncpname);
1388 return (NWAM_SUCCESS);
1391 if ((err = nwam_ncu_update_enabled(ncuh, B_FALSE)) != NWAM_SUCCESS) {
1392 free(ncpname);
1393 return (err);
1396 err = nwam_disable(ncpname, ncuh);
1397 free(ncpname);
1399 /* nwamd may not be running, that's okay. */
1400 if (err == NWAM_ERROR_BIND)
1401 return (NWAM_SUCCESS);
1402 else
1403 return (err);
1406 nwam_error_t
1407 nwam_ncu_destroy(nwam_ncu_handle_t ncuh, uint64_t flags)
1409 char *ncpname, *ncpfile;
1410 boolean_t read_only;
1411 nwam_error_t err;
1413 assert(ncuh != NULL);
1415 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1416 return (err);
1417 if (read_only)
1418 return (NWAM_ENTITY_NOT_DESTROYABLE);
1420 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1421 != NWAM_SUCCESS)
1422 return (err);
1423 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile))
1424 != NWAM_SUCCESS) {
1425 free(ncpname);
1426 return (err);
1429 err = nwam_destroy(ncpfile, ncuh, flags);
1431 free(ncpname);
1432 free(ncpfile);
1434 return (err);
1437 nwam_error_t
1438 nwam_ncu_get_prop_description(const char *propname, const char **descriptionp)
1440 return (nwam_get_prop_description(ncu_prop_table, propname,
1441 descriptionp));
1444 /* Get expected property data type */
1445 nwam_error_t
1446 nwam_ncu_get_prop_type(const char *propname, nwam_value_type_t *typep)
1448 return (nwam_get_prop_type(ncu_prop_table, propname, typep));
1451 nwam_error_t
1452 nwam_ncu_prop_read_only(const char *propname, boolean_t *readp)
1454 if ((*readp = NWAM_NCU_PROP_SETONCE(propname)) == B_TRUE)
1455 return (NWAM_SUCCESS);
1457 return (nwam_prop_read_only(ncu_prop_table, propname, readp));
1460 nwam_error_t
1461 nwam_ncu_prop_multivalued(const char *propname, boolean_t *multip)
1463 return (nwam_prop_multivalued(ncu_prop_table, propname, multip));
1467 * Ensure that the properties in the ncu, determined by that ncu's
1468 * type and class, belong there.
1470 static nwam_error_t
1471 nwam_ncu_validate_prop_membership(nwam_ncu_handle_t ncuh, const char *propname)
1473 struct nwam_prop_table_entry *pte;
1474 nwam_value_t typeval, classval;
1475 uint64_t type, class;
1476 uint64_t typeflags = 0, classflags = 0;
1478 /* Get type/class from ncu */
1479 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval)
1480 != NWAM_SUCCESS)
1481 return (NWAM_ENTITY_INVALID);
1482 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1483 nwam_value_free(typeval);
1484 return (NWAM_ENTITY_INVALID);
1486 typeflags = nwam_ncu_type_to_flag((nwam_ncu_type_t)type);
1487 nwam_value_free(typeval);
1489 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS, &classval)
1490 != NWAM_SUCCESS)
1491 return (NWAM_ENTITY_INVALID);
1492 if (nwam_value_get_uint64(classval, &class) != NWAM_SUCCESS) {
1493 nwam_value_free(classval);
1494 return (NWAM_ENTITY_INVALID);
1496 classflags = nwam_ncu_class_to_flag((nwam_ncu_class_t)class);
1497 nwam_value_free(classval);
1499 if ((pte = nwam_get_prop_table_entry(ncu_prop_table, propname)) == NULL)
1500 return (NWAM_INVALID_ARG);
1502 if (typeflags & pte->prop_type_membership &&
1503 classflags & pte->prop_class_membership) {
1504 return (NWAM_SUCCESS);
1505 } else {
1506 return (NWAM_ENTITY_INVALID_MEMBER);
1510 /* Validate property's ncu membership and type, number and range of values */
1511 nwam_error_t
1512 nwam_ncu_validate_prop(nwam_ncu_handle_t ncuh, const char *propname,
1513 nwam_value_t value)
1515 nwam_error_t err;
1517 assert(ncuh != NULL && propname != NULL);
1519 /* First, determine if this property is valid for this ncu */
1520 if ((err = nwam_ncu_validate_prop_membership(ncuh, propname))
1521 != NWAM_SUCCESS)
1522 return (err);
1524 return (nwam_validate_prop(ncu_prop_table, ncuh, propname, value));
1527 /* Property-specific value validation functions follow */
1529 static nwam_error_t
1530 valid_type(nwam_value_t value)
1532 uint64_t type;
1534 if (nwam_value_get_uint64(value, &type) != NWAM_SUCCESS ||
1535 type > NWAM_NCU_TYPE_INTERFACE)
1536 return (NWAM_ENTITY_INVALID_VALUE);
1537 return (NWAM_SUCCESS);
1540 static nwam_error_t
1541 valid_class(nwam_value_t value)
1543 uint64_t class;
1545 if (nwam_value_get_uint64(value, &class) != NWAM_SUCCESS ||
1546 class > NWAM_NCU_CLASS_IP)
1547 return (NWAM_ENTITY_INVALID_VALUE);
1548 return (NWAM_SUCCESS);
1551 static nwam_error_t
1552 valid_ncp(nwam_value_t value)
1554 char *ncp;
1556 if (nwam_value_get_string(value, &ncp) != NWAM_SUCCESS)
1557 return (NWAM_ENTITY_INVALID_VALUE);
1558 return (NWAM_SUCCESS);
1561 static nwam_error_t
1562 valid_priority_mode(nwam_value_t value)
1564 uint64_t priority_mode;
1566 if (nwam_value_get_uint64(value, &priority_mode) != NWAM_SUCCESS ||
1567 priority_mode > NWAM_PRIORITY_MODE_ALL)
1568 return (NWAM_ENTITY_INVALID_VALUE);
1569 return (NWAM_SUCCESS);
1572 static nwam_error_t
1573 valid_ncu_activation_mode(nwam_value_t value)
1575 uint64_t activation_mode;
1577 if (nwam_value_get_uint64(value, &activation_mode) != NWAM_SUCCESS)
1578 return (NWAM_ENTITY_INVALID_VALUE);
1580 switch (activation_mode) {
1581 case NWAM_ACTIVATION_MODE_MANUAL:
1582 case NWAM_ACTIVATION_MODE_PRIORITIZED:
1583 return (NWAM_SUCCESS);
1585 return (NWAM_ENTITY_INVALID_VALUE);
1588 /* ARGSUSED0 */
1589 static nwam_error_t
1590 valid_link_autopush(nwam_value_t value)
1592 return (NWAM_SUCCESS);
1595 static nwam_error_t
1596 valid_ip_version(nwam_value_t value)
1598 uint64_t *versions;
1599 uint_t i, numvalues;
1601 if (nwam_value_get_uint64_array(value, &versions, &numvalues)
1602 != NWAM_SUCCESS)
1603 return (NWAM_ENTITY_INVALID_VALUE);
1605 for (i = 0; i < numvalues; i++) {
1606 if (versions[i] != IPV4_VERSION &&
1607 versions[i] != IPV6_VERSION)
1608 return (NWAM_ENTITY_INVALID_VALUE);
1610 return (NWAM_SUCCESS);
1613 static nwam_error_t
1614 valid_addrsrc_v4(nwam_value_t value)
1616 uint64_t *addrsrc;
1617 uint_t i, numvalues;
1619 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1620 != NWAM_SUCCESS)
1621 return (NWAM_ENTITY_INVALID_VALUE);
1623 for (i = 0; i < numvalues; i++) {
1624 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1625 addrsrc[i] != NWAM_ADDRSRC_STATIC)
1626 return (NWAM_ENTITY_INVALID_VALUE);
1628 return (NWAM_SUCCESS);
1631 static nwam_error_t
1632 valid_addrsrc_v6(nwam_value_t value)
1634 uint64_t *addrsrc;
1635 uint_t i, numvalues;
1636 boolean_t dhcp_found = B_FALSE, autoconf_found = B_FALSE;
1638 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1639 != NWAM_SUCCESS)
1640 return (NWAM_ENTITY_INVALID_VALUE);
1642 for (i = 0; i < numvalues; i++) {
1643 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1644 addrsrc[i] != NWAM_ADDRSRC_STATIC &&
1645 addrsrc[i] != NWAM_ADDRSRC_AUTOCONF)
1646 return (NWAM_ENTITY_INVALID_VALUE);
1647 if (addrsrc[i] == NWAM_ADDRSRC_DHCP)
1648 dhcp_found = B_TRUE;
1649 if (addrsrc[i] == NWAM_ADDRSRC_AUTOCONF)
1650 autoconf_found = B_TRUE;
1653 * DHCP and AUTOCONF need to be specified as v6 address sources
1654 * since there is no way to switch them off in NWAM at present.
1656 if (dhcp_found && autoconf_found)
1657 return (NWAM_SUCCESS);
1658 else
1659 return (NWAM_ENTITY_INVALID_VALUE);
1662 static nwam_error_t
1663 valid_reqhost(nwam_value_t value)
1665 char *hostname;
1667 if (nwam_value_get_string(value, &hostname) != NWAM_SUCCESS)
1668 return (NWAM_ENTITY_INVALID_VALUE);
1669 return (ipadm_is_valid_hostname(hostname) ? NWAM_SUCCESS
1670 : NWAM_ENTITY_INVALID_VALUE);
1673 /* ARGSUSED0 */
1674 static nwam_error_t
1675 valid_link_mtu(nwam_value_t value)
1677 return (NWAM_SUCCESS);
1680 nwam_error_t
1681 nwam_ncu_validate(nwam_ncu_handle_t ncuh, const char **errpropp)
1683 return (nwam_validate(ncu_prop_table, ncuh, errpropp));
1687 * Given the ncu type and ncu class, return the list of properties that needs
1688 * to be set. Note this list is a complete property list that includes both
1689 * the required ones and the optional ones. Caller needs to free prop_list.
1691 nwam_error_t
1692 nwam_ncu_get_default_proplist(nwam_ncu_type_t type, nwam_ncu_class_t class,
1693 const char ***prop_list, uint_t *numvalues)
1695 uint64_t typeflags = nwam_ncu_type_to_flag(type);
1696 uint64_t classflags = nwam_ncu_class_to_flag(class);
1698 return (nwam_get_default_proplist(ncu_prop_table, typeflags,
1699 classflags, prop_list, numvalues));
1702 nwam_error_t
1703 nwam_ncp_get_state(nwam_ncp_handle_t ncph, nwam_state_t *statep,
1704 nwam_aux_state_t *auxp)
1706 return (nwam_get_state(ncph->nwh_name, ncph, statep, auxp));
1709 nwam_error_t
1710 nwam_ncu_get_state(nwam_ncu_handle_t ncuh, nwam_state_t *statep,
1711 nwam_aux_state_t *auxp)
1713 nwam_ncp_handle_t ncph;
1714 char *ncpname;
1715 nwam_error_t err;
1717 assert(ncuh != NULL);
1719 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
1720 return (err);
1721 if (!nwam_ncp_is_active(ncph)) {
1722 nwam_ncp_free(ncph);
1723 return (NWAM_ENTITY_INVALID);
1725 nwam_ncp_free(ncph);
1727 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1728 != NWAM_SUCCESS)
1729 return (err);
1731 err = nwam_request_state(NWAM_OBJECT_TYPE_NCU, ncuh->nwh_name, ncpname,
1732 statep, auxp);
1733 free(ncpname);
1734 return (err);
1737 nwam_error_t
1738 nwam_ncp_get_active_priority_group(int64_t *priorityp)
1740 return (nwam_request_active_priority_group(priorityp));