1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
26 */
27
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>
44
45 #include "libnwam_impl.h"
46 #include <libnwam_priv.h>
47 #include <libnwam.h>
48
49 /*
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.
60 */
61
62 /*
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.
66 */
67
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);
79
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},
165 };
166
167 #define NWAM_NUM_NCU_PROPS (sizeof (ncu_prop_table_entries) / \
168 sizeof (*ncu_prop_table_entries))
169
170 struct nwam_prop_table ncu_prop_table =
171 { NWAM_NUM_NCU_PROPS, ncu_prop_table_entries };
172
173 nwam_error_t
nwam_ncp_get_name(nwam_ncp_handle_t ncph,char ** namep)174 nwam_ncp_get_name(nwam_ncp_handle_t ncph, char **namep)
175 {
176 return (nwam_get_name(ncph, namep));
177 }
178
179 static nwam_error_t
nwam_ncp_name_to_file(const char * name,char ** filename)180 nwam_ncp_name_to_file(const char *name, char **filename)
181 {
182 assert(name != NULL && filename != NULL);
183
184 if ((*filename = malloc(MAXPATHLEN)) == NULL)
185 return (NWAM_NO_MEMORY);
186
187 (void) snprintf(*filename, MAXPATHLEN, "%s%s%s%s", NWAM_CONF_DIR,
188 NWAM_NCP_CONF_FILE_PRE, name, NWAM_NCP_CONF_FILE_SUF);
189
190 return (NWAM_SUCCESS);
191 }
192
193 /* ARGSUSED1 */
194 nwam_error_t
nwam_ncp_create(const char * name,uint64_t flags,nwam_ncp_handle_t * ncphp)195 nwam_ncp_create(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
196 {
197 nwam_error_t err;
198 char *ncpfile;
199
200 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, name, ncphp))
201 != NWAM_SUCCESS)
202 return (err);
203
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);
210 }
211
212 if ((err = nwam_commit(ncpfile, *ncphp, flags)) != NWAM_SUCCESS) {
213 nwam_free(*ncphp);
214 *ncphp = NULL;
215 }
216
217 free(ncpfile);
218
219 return (err);
220 }
221
222 /* Used by libnwam_files.c */
223 nwam_error_t
nwam_ncp_file_to_name(const char * path,char ** name)224 nwam_ncp_file_to_name(const char *path, char **name)
225 {
226 char path_copy[MAXPATHLEN];
227 char *filename, *suffix;
228
229 assert(path != NULL && name != NULL);
230
231 /* Make a copy as basename(3c) may modify string */
232 (void) strlcpy(path_copy, path, MAXPATHLEN);
233
234 if ((*name = malloc(NWAM_MAX_NAME_LEN)) == NULL)
235 return (NWAM_NO_MEMORY);
236
237 if ((filename = basename(path_copy)) == NULL) {
238 free(*name);
239 return (NWAM_ENTITY_INVALID);
240 }
241
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);
246 }
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);
251 }
252 suffix[0] = '\0';
253
254 return (NWAM_SUCCESS);
255 }
256
257 /* ARGSUSED1 */
258 nwam_error_t
nwam_ncp_read(const char * name,uint64_t flags,nwam_ncp_handle_t * ncphp)259 nwam_ncp_read(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
260 {
261 char *filename;
262 nwam_error_t err;
263
264 assert(name != NULL && ncphp != NULL);
265
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);
270 }
271
272 err = nwam_read(NWAM_OBJECT_TYPE_NCP, filename, name, flags, ncphp);
273 free(filename);
274 return (err);
275 }
276
277 static nwam_error_t
nwam_ncu_get_parent_ncp_name(nwam_ncu_handle_t ncuh,char ** parentnamep)278 nwam_ncu_get_parent_ncp_name(nwam_ncu_handle_t ncuh, char **parentnamep)
279 {
280 nwam_value_t parentval = NULL;
281 char *parentname;
282 nwam_error_t err;
283
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);
293 }
294 nwam_value_free(parentval);
295
296 return (NWAM_SUCCESS);
297 }
298
299 static int
nwam_ncp_copy_callback(nwam_ncu_handle_t oldncuh,void * arg)300 nwam_ncp_copy_callback(nwam_ncu_handle_t oldncuh, void *arg)
301 {
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;
308
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;
320
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;
329
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;
339
340 /* Save the new NCU */
341 err = nwam_commit(newfilename, newncuh, 0);
342
343 fail:
344 free(oldfilename);
345 free(newfilename);
346 nwam_ncu_free(newncuh);
347 return (err);
348 }
349
350 nwam_error_t
nwam_ncp_copy(nwam_ncp_handle_t oldncph,const char * newname,nwam_ncp_handle_t * newncphp)351 nwam_ncp_copy(nwam_ncp_handle_t oldncph, const char *newname,
352 nwam_ncp_handle_t *newncphp)
353 {
354 nwam_ncp_handle_t ncph;
355 nwam_error_t err;
356 int cb_ret;
357
358 assert(oldncph != NULL && newname != NULL && newncphp != NULL);
359
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);
365 }
366
367 /* create new handle */
368 if ((err = nwam_ncp_create(newname, 0, newncphp)) != NWAM_SUCCESS)
369 return (err);
370
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);
381 }
382
383 return (NWAM_SUCCESS);
384 }
385
386 /*
387 * Convert type to flag
388 */
389 static uint64_t
nwam_ncu_type_to_flag(nwam_ncu_type_t type)390 nwam_ncu_type_to_flag(nwam_ncu_type_t type)
391 {
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);
401 }
402 }
403
404 /*
405 * Convert class to flag
406 */
407 uint64_t
nwam_ncu_class_to_flag(nwam_ncu_class_t class)408 nwam_ncu_class_to_flag(nwam_ncu_class_t class)
409 {
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);
419 }
420 }
421
422 /*
423 * Infer NCU type from NCU class
424 */
425 nwam_ncu_type_t
nwam_ncu_class_to_type(nwam_ncu_class_t class)426 nwam_ncu_class_to_type(nwam_ncu_class_t class)
427 {
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);
437 }
438 }
439
440 /*
441 * Make ncp active, deactivating any other active ncp.
442 */
443 nwam_error_t
nwam_ncp_enable(nwam_ncp_handle_t ncph)444 nwam_ncp_enable(nwam_ncp_handle_t ncph)
445 {
446 nwam_error_t err;
447 char *name;
448
449 assert(ncph != NULL);
450
451 err = nwam_enable(NULL, ncph);
452
453 if (err == NWAM_ERROR_BIND) {
454 /*
455 * nwamd is not running, set active_ncp property so when
456 * nwamd is next started, this NCP will be used.
457 */
458 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
459 return (err);
460
461 err = nwam_set_smf_string_property(NWAM_FMRI, NWAM_PG,
462 NWAM_PROP_ACTIVE_NCP, name);
463 free(name);
464 }
465
466 return (err);
467 }
468
469 /* Compare NCP names c1 and c2 using strcasecmp() */
470 static int
ncpname_cmp(const void * c1,const void * c2)471 ncpname_cmp(const void *c1, const void *c2)
472 {
473 return (strcasecmp(*(const char **)c1, *(const char **)c2));
474 }
475
476 /* ARGSUSED1 */
477 nwam_error_t
nwam_walk_ncps(int (* cb)(nwam_ncp_handle_t,void *),void * data,uint64_t flags,int * retp)478 nwam_walk_ncps(int (*cb)(nwam_ncp_handle_t, void *), void *data,
479 uint64_t flags, int *retp)
480 {
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;
488
489 assert(cb != NULL);
490
491 if ((err = nwam_valid_flags(flags, NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
492 return (err);
493 /*
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).
499 */
500 if ((err = nwam_read_object_from_backend(NULL, NULL, flags,
501 &objlist)) != NWAM_SUCCESS)
502 return (err);
503
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);
508 }
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);
514 }
515
516 /* sort the NCP names alphabetically */
517 qsort(ncpfiles, num_ncpfiles, sizeof (char *), ncpname_cmp);
518
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;
527 }
528 ret = cb(ncph, data);
529 free(ncph);
530 free(ncpname);
531 if (ret != 0) {
532 err = NWAM_WALK_HALTED;
533 break;
534 }
535 }
536 nwam_value_free(value);
537 nwam_free_object_list(objlist);
538
539 if (retp != NULL)
540 *retp = ret;
541 return (err);
542 }
543
544 /*
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).
547 */
548 nwam_error_t
nwam_ncp_get_read_only(nwam_ncp_handle_t ncph,boolean_t * readp)549 nwam_ncp_get_read_only(nwam_ncp_handle_t ncph, boolean_t *readp)
550 {
551 nwam_error_t err;
552 char *name;
553
554 assert(ncph != NULL && readp != NULL);
555
556 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
557 return (err);
558
559 if (NWAM_NCP_AUTOMATIC(name))
560 *readp = !nwam_uid_is_special();
561 else
562 *readp = B_FALSE;
563
564 free(name);
565 return (NWAM_SUCCESS);
566 }
567
568 /* Checks if NCU is writable depending on its parent */
569 nwam_error_t
nwam_ncu_get_read_only(nwam_ncu_handle_t ncuh,boolean_t * readp)570 nwam_ncu_get_read_only(nwam_ncu_handle_t ncuh, boolean_t *readp)
571 {
572 nwam_error_t err;
573 nwam_ncp_handle_t ncph;
574
575 assert(ncuh != NULL && readp != NULL);
576
577 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
578 return (err);
579
580 err = nwam_ncp_get_read_only(ncph, readp);
581 nwam_ncp_free(ncph);
582 return (err);
583 }
584
585 /* Returns true if the NCP is active */
586 static boolean_t
nwam_ncp_is_active(nwam_ncp_handle_t ncph)587 nwam_ncp_is_active(nwam_ncp_handle_t ncph)
588 {
589 char *active_ncp, *name;
590 boolean_t ret;
591
592 assert(ncph != NULL);
593
594 /*
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.
598 */
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);
603
604 ret = (strcmp(name, active_ncp) == 0);
605
606 free(active_ncp);
607 free(name);
608
609 return (ret);
610 }
611
612 nwam_error_t
nwam_ncp_destroy(nwam_ncp_handle_t ncph,uint64_t flags)613 nwam_ncp_destroy(nwam_ncp_handle_t ncph, uint64_t flags)
614 {
615 char *filename;
616 nwam_error_t err;
617 boolean_t read_only;
618
619 assert(ncph != NULL);
620
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);
625
626 if (nwam_ncp_is_active(ncph))
627 return (NWAM_ENTITY_IN_USE);
628
629 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &filename))
630 != NWAM_SUCCESS)
631 return (err);
632
633 err = nwam_destroy(filename, ncph, flags);
634 free(filename);
635
636 return (NWAM_SUCCESS);
637 }
638
639 static nwam_error_t
nwam_ncu_internal_name_to_name(const char * internalname,nwam_ncu_type_t * typep,char ** namep)640 nwam_ncu_internal_name_to_name(const char *internalname,
641 nwam_ncu_type_t *typep, char **namep)
642 {
643 char *prefixstr;
644
645 assert(internalname != NULL && namep != NULL);
646
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);
657 }
658
659 *namep = strdup(internalname + strlen(prefixstr));
660 if (*namep == NULL)
661 return (NWAM_NO_MEMORY);
662 return (NWAM_SUCCESS);
663 }
664
665 /* ARGSUSED2 */
666 static int
ncu_selectcb(struct nwam_handle * hp,uint64_t flags,void * data)667 ncu_selectcb(struct nwam_handle *hp, uint64_t flags, void *data)
668 {
669 nwam_ncu_handle_t ncuh = hp;
670 nwam_value_t typeval = NULL, classval = NULL;
671 uint64_t type, class, matchflags, walkfilter;
672
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);
680 }
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);
686 }
687
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);
692
693 if ((walkfilter = (flags & NWAM_WALK_FILTER_MASK)) == 0)
694 walkfilter = NWAM_FLAG_NCU_TYPE_CLASS_ALL;
695
696 if (matchflags & walkfilter)
697 return (NWAM_SUCCESS);
698 return (NWAM_INVALID_ARG);
699 }
700
701 nwam_error_t
nwam_ncp_walk_ncus(nwam_ncp_handle_t ncph,int (* cb)(nwam_ncu_handle_t,void *),void * data,uint64_t flags,int * retp)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)
704 {
705 char *ncpfile;
706 nwam_error_t err;
707
708 assert(ncph != NULL && cb != NULL);
709
710 if ((err = nwam_valid_flags(flags,
711 NWAM_FLAG_NCU_TYPE_CLASS_ALL | NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
712 return (err);
713
714 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
715 != NWAM_SUCCESS)
716 return (err);
717
718 err = nwam_walk(NWAM_OBJECT_TYPE_NCU, ncpfile, cb, data, flags,
719 retp, ncu_selectcb);
720 free(ncpfile);
721
722 return (err);
723 }
724
725 void
nwam_ncp_free(nwam_ncp_handle_t ncph)726 nwam_ncp_free(nwam_ncp_handle_t ncph)
727 {
728 nwam_free(ncph);
729 }
730
731 /*
732 * Are ncu type and class compatible?
733 */
734 static boolean_t
nwam_ncu_type_class_compatible(nwam_ncu_type_t type,nwam_ncu_class_t class)735 nwam_ncu_type_class_compatible(nwam_ncu_type_t type, nwam_ncu_class_t class)
736 {
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);
744 }
745 }
746
747 /* Name to validate may be internal name. If so, convert it before validating */
748 static boolean_t
valid_ncu_name(const char * name)749 valid_ncu_name(const char *name)
750 {
751 char *n;
752 boolean_t ret;
753 nwam_ncu_type_t type;
754
755 if (nwam_ncu_internal_name_to_name(name, &type, &n) == NWAM_SUCCESS) {
756
757 ret = dladm_valid_linkname(n);
758 free(n);
759 } else {
760 ret = dladm_valid_linkname(name);
761 }
762
763 return (ret);
764 }
765
766 nwam_error_t
nwam_ncu_create(nwam_ncp_handle_t ncph,const char * name,nwam_ncu_type_t type,nwam_ncu_class_t class,nwam_ncu_handle_t * ncuhp)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)
769 {
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;
776
777 assert(ncph != NULL && name != NULL && ncuhp != NULL);
778
779 if (!valid_ncu_name(name))
780 return (NWAM_INVALID_ARG);
781
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);
786
787 if (nwam_ncu_read(ncph, name, type, 0, &ncuh) == NWAM_SUCCESS) {
788 nwam_ncu_free(ncuh);
789 return (NWAM_ENTITY_EXISTS);
790 }
791
792 if (!valid_ncu_name(name) ||
793 !nwam_ncu_type_class_compatible(type, class))
794 return (NWAM_INVALID_ARG);
795
796 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname))
797 != NWAM_SUCCESS)
798 return (err);
799
800 /* Create handle */
801 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, typedname, ncuhp))
802 != NWAM_SUCCESS)
803 return (err);
804 free(typedname);
805
806 /*
807 * Create new object list for NCU. The new NCU is initialized with
808 * the appropriate type and class.
809 */
810 if ((err = nwam_alloc_object_list(&(*ncuhp)->nwh_data)) != NWAM_SUCCESS)
811 goto finish;
812
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;
822 }
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;
832 }
833
834 /* Set default IP, datalink properties */
835 if (type == NWAM_NCU_TYPE_INTERFACE && class == NWAM_NCU_CLASS_IP) {
836
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;
841
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;
851 }
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);
858 }
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);
870 }
871
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;
880 }
881 return (err);
882 }
883
884 nwam_error_t
nwam_ncu_read(nwam_ncp_handle_t ncph,const char * name,nwam_ncu_type_t type,uint64_t flags,nwam_ncu_handle_t * ncuhp)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)
887 {
888 char *ncpfile, *typedname;
889 nwam_error_t err, err_ip, err_link;
890 nwam_ncu_handle_t ncuh_ip, ncuh_link;
891
892 assert(ncph != NULL && name != NULL && ncuhp != NULL);
893
894 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
895 != NWAM_SUCCESS)
896 return (err);
897
898 if (type == NWAM_NCU_TYPE_ANY) {
899
900 free(ncpfile);
901
902 /*
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.
907 */
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);
912
913 *ncuhp = NULL;
914
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;
926 }
927 err = NWAM_SUCCESS;
928 }
929
930 return (err);
931 }
932 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname)) !=
933 NWAM_SUCCESS) {
934 free(ncpfile);
935 return (err);
936 }
937 err = nwam_read(NWAM_OBJECT_TYPE_NCU, ncpfile, typedname, flags, ncuhp);
938
939 free(typedname);
940 free(ncpfile);
941
942 return (err);
943 }
944
945 nwam_error_t
nwam_ncu_get_name(nwam_ncu_handle_t ncuh,char ** namep)946 nwam_ncu_get_name(nwam_ncu_handle_t ncuh, char **namep)
947 {
948 nwam_ncu_type_t type;
949
950 assert(ncuh != NULL && namep != NULL);
951
952 return (nwam_ncu_internal_name_to_name(ncuh->nwh_name, &type, namep));
953 }
954
955 nwam_error_t
nwam_ncu_name_to_typed_name(const char * name,nwam_ncu_type_t type,char ** typednamep)956 nwam_ncu_name_to_typed_name(const char *name, nwam_ncu_type_t type,
957 char **typednamep)
958 {
959 char *prefixstr;
960 size_t typednamesz;
961
962 assert(name != NULL && typednamep != NULL);
963
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);
973 }
974 typednamesz = strlen(name) + strlen(prefixstr) + 1;
975 if ((*typednamep = malloc(typednamesz)) == NULL)
976 return (NWAM_NO_MEMORY);
977
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);
984 }
985
986 return (NWAM_SUCCESS);
987 }
988
989 nwam_error_t
nwam_ncu_typed_name_to_name(const char * typed_name,nwam_ncu_type_t * typep,char ** name)990 nwam_ncu_typed_name_to_name(const char *typed_name, nwam_ncu_type_t *typep,
991 char **name)
992 {
993 return (nwam_ncu_internal_name_to_name(typed_name, typep, name));
994 }
995
996 void
nwam_ncu_free(nwam_ncu_handle_t ncuh)997 nwam_ncu_free(nwam_ncu_handle_t ncuh)
998 {
999 nwam_free(ncuh);
1000 }
1001
1002 nwam_error_t
nwam_ncu_copy(nwam_ncu_handle_t oldncuh,const char * newname,nwam_ncu_handle_t * newncuhp)1003 nwam_ncu_copy(nwam_ncu_handle_t oldncuh, const char *newname,
1004 nwam_ncu_handle_t *newncuhp)
1005 {
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;
1012
1013 assert(oldncuh != NULL && newname != NULL && newncuhp != NULL);
1014
1015 if (nwam_ncu_get_prop_value(oldncuh, NWAM_NCU_PROP_TYPE,
1016 &typeval) != NWAM_SUCCESS) {
1017 return (NWAM_INVALID_ARG);
1018 }
1019 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1020 nwam_value_free(typeval);
1021 return (NWAM_INVALID_ARG);
1022 }
1023 nwam_value_free(typeval);
1024
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);
1032 }
1033 nwam_ncp_free(ncph);
1034
1035 if ((err = nwam_ncu_name_to_typed_name(newname, type, &typednewname))
1036 != NWAM_SUCCESS)
1037 return (err);
1038
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);
1048 }
1049
1050 return (NWAM_SUCCESS);
1051 }
1052
1053 nwam_error_t
nwam_ncu_delete_prop(nwam_ncu_handle_t ncuh,const char * propname)1054 nwam_ncu_delete_prop(nwam_ncu_handle_t ncuh, const char *propname)
1055 {
1056 boolean_t ro_ncu, ro_prop;
1057 nwam_error_t err;
1058 void *olddata;
1059
1060 assert(ncuh != NULL && propname != NULL);
1061
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);
1067
1068 /*
1069 * Duplicate data, remove property and validate. If validation
1070 * fails, revert to data duplicated prior to remove.
1071 */
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);
1080 }
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);
1085 }
1086 nwam_free_object_list(olddata);
1087
1088 return (NWAM_SUCCESS);
1089 }
1090
1091 nwam_error_t
nwam_ncu_set_prop_value(nwam_ncu_handle_t ncuh,const char * propname,nwam_value_t value)1092 nwam_ncu_set_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1093 nwam_value_t value)
1094 {
1095 boolean_t ro_ncu, ro_prop;
1096 nwam_error_t err;
1097 nwam_ncp_handle_t ncph;
1098
1099 assert(ncuh != NULL && propname != NULL && value != NULL);
1100
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);
1106
1107 err = nwam_ncu_get_ncp(ncuh, &ncph);
1108 if (err != NWAM_SUCCESS && err != NWAM_INVALID_ARG) {
1109 /*
1110 * If "parent" property doesn't exist, NWAM_INVALID_ARG
1111 * is returned. Allow the setting to continue.
1112 */
1113 return (err);
1114 }
1115 nwam_ncp_free(ncph);
1116
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);
1121
1122 return (nwam_set_prop_value(ncuh->nwh_data, propname, value));
1123 }
1124
1125 nwam_error_t
nwam_ncu_get_prop_value(nwam_ncu_handle_t ncuh,const char * propname,nwam_value_t * valuep)1126 nwam_ncu_get_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1127 nwam_value_t *valuep)
1128 {
1129 assert(ncuh != NULL && propname != NULL && valuep != NULL);
1130
1131 return (nwam_get_prop_value(ncuh->nwh_data, propname, valuep));
1132 }
1133
1134 nwam_error_t
nwam_ncu_walk_props(nwam_ncu_handle_t ncuh,int (* cb)(const char *,nwam_value_t,void *),void * data,uint64_t flags,int * retp)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)
1138 {
1139 return (nwam_walk_props(ncuh, cb, data, flags, retp));
1140 }
1141
1142 nwam_error_t
nwam_ncu_get_ncp(nwam_ncu_handle_t ncuh,nwam_ncp_handle_t * ncphp)1143 nwam_ncu_get_ncp(nwam_ncu_handle_t ncuh, nwam_ncp_handle_t *ncphp)
1144 {
1145 nwam_error_t err;
1146 char *parentname = NULL;
1147
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 if (parentname != NULL)
1153 free(parentname);
1154 return (err);
1155 }
1156 free(parentname);
1157
1158 return (NWAM_SUCCESS);
1159 }
1160
1161 nwam_error_t
nwam_ncu_commit(nwam_ncu_handle_t ncuh,uint64_t flags)1162 nwam_ncu_commit(nwam_ncu_handle_t ncuh, uint64_t flags)
1163 {
1164 nwam_error_t err;
1165 boolean_t read_only;
1166 char *ncpfile, *ncpname;
1167
1168 assert(ncuh != NULL && ncuh->nwh_data != NULL);
1169
1170 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1171 return (err);
1172 if (read_only)
1173 return (NWAM_ENTITY_READ_ONLY);
1174
1175 if ((err = nwam_ncu_validate(ncuh, NULL)) != NWAM_SUCCESS ||
1176 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1177 != NWAM_SUCCESS)
1178 return (err);
1179
1180 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile)) != NWAM_SUCCESS) {
1181 free(ncpname);
1182 return (err);
1183 }
1184
1185 err = nwam_commit(ncpfile, ncuh, flags);
1186
1187 free(ncpname);
1188 free(ncpfile);
1189
1190 return (err);
1191 }
1192 /* Get the NCU type */
1193 nwam_error_t
nwam_ncu_get_ncu_type(nwam_ncu_handle_t ncuh,nwam_ncu_type_t * typep)1194 nwam_ncu_get_ncu_type(nwam_ncu_handle_t ncuh, nwam_ncu_type_t *typep)
1195 {
1196 nwam_error_t err;
1197 nwam_value_t typeval;
1198 uint64_t type;
1199
1200 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval))
1201 != NWAM_SUCCESS)
1202 return (err);
1203 err = nwam_value_get_uint64(typeval, &type);
1204 nwam_value_free(typeval);
1205 if (err != NWAM_SUCCESS)
1206 return (err);
1207
1208 *typep = type;
1209 return (NWAM_SUCCESS);
1210 }
1211
1212 /* Get the NCU class */
1213 nwam_error_t
nwam_ncu_get_ncu_class(nwam_ncu_handle_t ncuh,nwam_ncu_class_t * classp)1214 nwam_ncu_get_ncu_class(nwam_ncu_handle_t ncuh, nwam_ncu_class_t *classp)
1215 {
1216 nwam_error_t err;
1217 nwam_value_t classval;
1218 uint64_t class;
1219
1220 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS,
1221 &classval)) != NWAM_SUCCESS)
1222 return (err);
1223 err = nwam_value_get_uint64(classval, &class);
1224 nwam_value_free(classval);
1225 if (err != NWAM_SUCCESS)
1226 return (err);
1227
1228 *classp = class;
1229 return (NWAM_SUCCESS);
1230 }
1231
1232 /*
1233 * Determine if the NCU has manual activation-mode or not.
1234 */
1235 nwam_error_t
nwam_ncu_is_manual(nwam_ncu_handle_t ncuh,boolean_t * manualp)1236 nwam_ncu_is_manual(nwam_ncu_handle_t ncuh, boolean_t *manualp)
1237 {
1238 nwam_error_t err;
1239 nwam_value_t actval;
1240 uint64_t activation;
1241
1242 assert(ncuh != NULL);
1243
1244 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ACTIVATION_MODE,
1245 &actval)) != NWAM_SUCCESS)
1246 return (err);
1247 err = nwam_value_get_uint64(actval, &activation);
1248 nwam_value_free(actval);
1249 if (err != NWAM_SUCCESS)
1250 return (err);
1251
1252 if (activation == NWAM_ACTIVATION_MODE_MANUAL)
1253 *manualp = B_TRUE;
1254 else
1255 *manualp = B_FALSE;
1256 return (NWAM_SUCCESS);
1257 }
1258
1259 /* Determine if NCU is enabled or not */
1260 static nwam_error_t
nwam_ncu_is_enabled(nwam_ncu_handle_t ncuh,boolean_t * enabledp)1261 nwam_ncu_is_enabled(nwam_ncu_handle_t ncuh, boolean_t *enabledp)
1262 {
1263 nwam_error_t err;
1264 nwam_value_t enabledval;
1265
1266 assert(ncuh != NULL);
1267
1268 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED,
1269 &enabledval)) != NWAM_SUCCESS)
1270 return (err);
1271 err = nwam_value_get_boolean(enabledval, enabledp);
1272 nwam_value_free(enabledval);
1273 return (err);
1274 }
1275
1276 /* Update the enabled property */
1277 static nwam_error_t
nwam_ncu_update_enabled(nwam_ncu_handle_t ncuh,boolean_t enabled)1278 nwam_ncu_update_enabled(nwam_ncu_handle_t ncuh, boolean_t enabled)
1279 {
1280 nwam_error_t err;
1281 nwam_value_t enabledval;
1282
1283 if ((err = nwam_value_create_boolean(enabled, &enabledval))
1284 != NWAM_SUCCESS)
1285 return (err);
1286 err = nwam_set_prop_value(ncuh->nwh_data, NWAM_NCU_PROP_ENABLED,
1287 enabledval);
1288 nwam_value_free(enabledval);
1289 if (err != NWAM_SUCCESS)
1290 return (err);
1291 return (nwam_ncu_commit(ncuh, NWAM_FLAG_ENTITY_ENABLE));
1292 }
1293
1294 /*
1295 * Make ncu active; fails if the NCU's parent NCP is not active.
1296 */
1297 nwam_error_t
nwam_ncu_enable(nwam_ncu_handle_t ncuh)1298 nwam_ncu_enable(nwam_ncu_handle_t ncuh)
1299 {
1300 char *ncpname = NULL;
1301 nwam_error_t err;
1302 nwam_ncu_type_t type;
1303 boolean_t read_only, enabled, manual;
1304
1305 assert(ncuh != NULL);
1306
1307 /* Don't allow NCUs of Automatic NCP to be enabled */
1308 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1309 return (err);
1310 if (read_only)
1311 return (NWAM_ENTITY_NOT_MANUAL);
1312
1313 /* Link NCUs with manual activation-mode or IP NCUs can be enabled */
1314 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1315 return (err);
1316
1317 if (type == NWAM_NCU_TYPE_LINK) {
1318 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1319 return (err);
1320 if (!manual)
1321 return (NWAM_ENTITY_NOT_MANUAL);
1322 }
1323
1324 /* Make sure NCU is not enabled */
1325 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1326 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1327 != NWAM_SUCCESS)
1328 return (err);
1329
1330 if (enabled) {
1331 free(ncpname);
1332 return (NWAM_SUCCESS);
1333 }
1334
1335 if ((err = nwam_ncu_update_enabled(ncuh, B_TRUE)) != NWAM_SUCCESS) {
1336 free(ncpname);
1337 return (err);
1338 }
1339
1340 err = nwam_enable(ncpname, ncuh);
1341 free(ncpname);
1342
1343 /* nwamd may not be running, that's okay. */
1344 if (err == NWAM_ERROR_BIND)
1345 return (NWAM_SUCCESS);
1346 else
1347 return (err);
1348 }
1349
1350 /*
1351 * Disable ncu; fails if the NCU's parent NCP is not active, or if the
1352 * NCU is not currently active.
1353 */
1354 nwam_error_t
nwam_ncu_disable(nwam_ncu_handle_t ncuh)1355 nwam_ncu_disable(nwam_ncu_handle_t ncuh)
1356 {
1357 char *ncpname = NULL;
1358 nwam_error_t err;
1359 nwam_ncu_type_t type;
1360 boolean_t read_only, enabled, manual;
1361
1362 assert(ncuh != NULL);
1363
1364 /* Don't allow NCUs of Automatic NCP to be disabled */
1365 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1366 return (err);
1367 if (read_only)
1368 return (NWAM_ENTITY_NOT_MANUAL);
1369
1370 /* Link NCUs with manual activation-mode or IP NCUs can be disabled */
1371 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1372 return (err);
1373
1374 if (type == NWAM_NCU_TYPE_LINK) {
1375 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1376 return (err);
1377 if (!manual)
1378 return (NWAM_ENTITY_NOT_MANUAL);
1379 }
1380
1381 /* Make sure NCU is enabled */
1382 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1383 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1384 != NWAM_SUCCESS)
1385 return (err);
1386
1387 if (!enabled) {
1388 free(ncpname);
1389 return (NWAM_SUCCESS);
1390 }
1391
1392 if ((err = nwam_ncu_update_enabled(ncuh, B_FALSE)) != NWAM_SUCCESS) {
1393 free(ncpname);
1394 return (err);
1395 }
1396
1397 err = nwam_disable(ncpname, ncuh);
1398 free(ncpname);
1399
1400 /* nwamd may not be running, that's okay. */
1401 if (err == NWAM_ERROR_BIND)
1402 return (NWAM_SUCCESS);
1403 else
1404 return (err);
1405 }
1406
1407 nwam_error_t
nwam_ncu_destroy(nwam_ncu_handle_t ncuh,uint64_t flags)1408 nwam_ncu_destroy(nwam_ncu_handle_t ncuh, uint64_t flags)
1409 {
1410 char *ncpname, *ncpfile;
1411 boolean_t read_only;
1412 nwam_error_t err;
1413
1414 assert(ncuh != NULL);
1415
1416 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1417 return (err);
1418 if (read_only)
1419 return (NWAM_ENTITY_NOT_DESTROYABLE);
1420
1421 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1422 != NWAM_SUCCESS)
1423 return (err);
1424 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile))
1425 != NWAM_SUCCESS) {
1426 free(ncpname);
1427 return (err);
1428 }
1429
1430 err = nwam_destroy(ncpfile, ncuh, flags);
1431
1432 free(ncpname);
1433 free(ncpfile);
1434
1435 return (err);
1436 }
1437
1438 nwam_error_t
nwam_ncu_get_prop_description(const char * propname,const char ** descriptionp)1439 nwam_ncu_get_prop_description(const char *propname, const char **descriptionp)
1440 {
1441 return (nwam_get_prop_description(ncu_prop_table, propname,
1442 descriptionp));
1443 }
1444
1445 /* Get expected property data type */
1446 nwam_error_t
nwam_ncu_get_prop_type(const char * propname,nwam_value_type_t * typep)1447 nwam_ncu_get_prop_type(const char *propname, nwam_value_type_t *typep)
1448 {
1449 return (nwam_get_prop_type(ncu_prop_table, propname, typep));
1450 }
1451
1452 nwam_error_t
nwam_ncu_prop_read_only(const char * propname,boolean_t * readp)1453 nwam_ncu_prop_read_only(const char *propname, boolean_t *readp)
1454 {
1455 if ((*readp = NWAM_NCU_PROP_SETONCE(propname)) == B_TRUE)
1456 return (NWAM_SUCCESS);
1457
1458 return (nwam_prop_read_only(ncu_prop_table, propname, readp));
1459 }
1460
1461 nwam_error_t
nwam_ncu_prop_multivalued(const char * propname,boolean_t * multip)1462 nwam_ncu_prop_multivalued(const char *propname, boolean_t *multip)
1463 {
1464 return (nwam_prop_multivalued(ncu_prop_table, propname, multip));
1465 }
1466
1467 /*
1468 * Ensure that the properties in the ncu, determined by that ncu's
1469 * type and class, belong there.
1470 */
1471 static nwam_error_t
nwam_ncu_validate_prop_membership(nwam_ncu_handle_t ncuh,const char * propname)1472 nwam_ncu_validate_prop_membership(nwam_ncu_handle_t ncuh, const char *propname)
1473 {
1474 struct nwam_prop_table_entry *pte;
1475 nwam_value_t typeval, classval;
1476 uint64_t type, class;
1477 uint64_t typeflags = 0, classflags = 0;
1478
1479 /* Get type/class from ncu */
1480 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval)
1481 != NWAM_SUCCESS)
1482 return (NWAM_ENTITY_INVALID);
1483 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1484 nwam_value_free(typeval);
1485 return (NWAM_ENTITY_INVALID);
1486 }
1487 typeflags = nwam_ncu_type_to_flag((nwam_ncu_type_t)type);
1488 nwam_value_free(typeval);
1489
1490 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS, &classval)
1491 != NWAM_SUCCESS)
1492 return (NWAM_ENTITY_INVALID);
1493 if (nwam_value_get_uint64(classval, &class) != NWAM_SUCCESS) {
1494 nwam_value_free(classval);
1495 return (NWAM_ENTITY_INVALID);
1496 }
1497 classflags = nwam_ncu_class_to_flag((nwam_ncu_class_t)class);
1498 nwam_value_free(classval);
1499
1500 if ((pte = nwam_get_prop_table_entry(ncu_prop_table, propname)) == NULL)
1501 return (NWAM_INVALID_ARG);
1502
1503 if (typeflags & pte->prop_type_membership &&
1504 classflags & pte->prop_class_membership) {
1505 return (NWAM_SUCCESS);
1506 } else {
1507 return (NWAM_ENTITY_INVALID_MEMBER);
1508 }
1509 }
1510
1511 /* Validate property's ncu membership and type, number and range of values */
1512 nwam_error_t
nwam_ncu_validate_prop(nwam_ncu_handle_t ncuh,const char * propname,nwam_value_t value)1513 nwam_ncu_validate_prop(nwam_ncu_handle_t ncuh, const char *propname,
1514 nwam_value_t value)
1515 {
1516 nwam_error_t err;
1517
1518 assert(ncuh != NULL && propname != NULL);
1519
1520 /* First, determine if this property is valid for this ncu */
1521 if ((err = nwam_ncu_validate_prop_membership(ncuh, propname))
1522 != NWAM_SUCCESS)
1523 return (err);
1524
1525 return (nwam_validate_prop(ncu_prop_table, ncuh, propname, value));
1526 }
1527
1528 /* Property-specific value validation functions follow */
1529
1530 static nwam_error_t
valid_type(nwam_value_t value)1531 valid_type(nwam_value_t value)
1532 {
1533 uint64_t type;
1534
1535 if (nwam_value_get_uint64(value, &type) != NWAM_SUCCESS ||
1536 type > NWAM_NCU_TYPE_INTERFACE)
1537 return (NWAM_ENTITY_INVALID_VALUE);
1538 return (NWAM_SUCCESS);
1539 }
1540
1541 static nwam_error_t
valid_class(nwam_value_t value)1542 valid_class(nwam_value_t value)
1543 {
1544 uint64_t class;
1545
1546 if (nwam_value_get_uint64(value, &class) != NWAM_SUCCESS ||
1547 class > NWAM_NCU_CLASS_IP)
1548 return (NWAM_ENTITY_INVALID_VALUE);
1549 return (NWAM_SUCCESS);
1550 }
1551
1552 static nwam_error_t
valid_ncp(nwam_value_t value)1553 valid_ncp(nwam_value_t value)
1554 {
1555 char *ncp;
1556
1557 if (nwam_value_get_string(value, &ncp) != NWAM_SUCCESS)
1558 return (NWAM_ENTITY_INVALID_VALUE);
1559 return (NWAM_SUCCESS);
1560 }
1561
1562 static nwam_error_t
valid_priority_mode(nwam_value_t value)1563 valid_priority_mode(nwam_value_t value)
1564 {
1565 uint64_t priority_mode;
1566
1567 if (nwam_value_get_uint64(value, &priority_mode) != NWAM_SUCCESS ||
1568 priority_mode > NWAM_PRIORITY_MODE_ALL)
1569 return (NWAM_ENTITY_INVALID_VALUE);
1570 return (NWAM_SUCCESS);
1571 }
1572
1573 static nwam_error_t
valid_ncu_activation_mode(nwam_value_t value)1574 valid_ncu_activation_mode(nwam_value_t value)
1575 {
1576 uint64_t activation_mode;
1577
1578 if (nwam_value_get_uint64(value, &activation_mode) != NWAM_SUCCESS)
1579 return (NWAM_ENTITY_INVALID_VALUE);
1580
1581 switch (activation_mode) {
1582 case NWAM_ACTIVATION_MODE_MANUAL:
1583 case NWAM_ACTIVATION_MODE_PRIORITIZED:
1584 return (NWAM_SUCCESS);
1585 }
1586 return (NWAM_ENTITY_INVALID_VALUE);
1587 }
1588
1589 /* ARGSUSED0 */
1590 static nwam_error_t
valid_link_autopush(nwam_value_t value)1591 valid_link_autopush(nwam_value_t value)
1592 {
1593 return (NWAM_SUCCESS);
1594 }
1595
1596 static nwam_error_t
valid_ip_version(nwam_value_t value)1597 valid_ip_version(nwam_value_t value)
1598 {
1599 uint64_t *versions;
1600 uint_t i, numvalues;
1601
1602 if (nwam_value_get_uint64_array(value, &versions, &numvalues)
1603 != NWAM_SUCCESS)
1604 return (NWAM_ENTITY_INVALID_VALUE);
1605
1606 for (i = 0; i < numvalues; i++) {
1607 if (versions[i] != IPV4_VERSION &&
1608 versions[i] != IPV6_VERSION)
1609 return (NWAM_ENTITY_INVALID_VALUE);
1610 }
1611 return (NWAM_SUCCESS);
1612 }
1613
1614 static nwam_error_t
valid_addrsrc_v4(nwam_value_t value)1615 valid_addrsrc_v4(nwam_value_t value)
1616 {
1617 uint64_t *addrsrc;
1618 uint_t i, numvalues;
1619
1620 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1621 != NWAM_SUCCESS)
1622 return (NWAM_ENTITY_INVALID_VALUE);
1623
1624 for (i = 0; i < numvalues; i++) {
1625 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1626 addrsrc[i] != NWAM_ADDRSRC_STATIC)
1627 return (NWAM_ENTITY_INVALID_VALUE);
1628 }
1629 return (NWAM_SUCCESS);
1630 }
1631
1632 static nwam_error_t
valid_addrsrc_v6(nwam_value_t value)1633 valid_addrsrc_v6(nwam_value_t value)
1634 {
1635 uint64_t *addrsrc;
1636 uint_t i, numvalues;
1637 boolean_t dhcp_found = B_FALSE, autoconf_found = B_FALSE;
1638
1639 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1640 != NWAM_SUCCESS)
1641 return (NWAM_ENTITY_INVALID_VALUE);
1642
1643 for (i = 0; i < numvalues; i++) {
1644 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1645 addrsrc[i] != NWAM_ADDRSRC_STATIC &&
1646 addrsrc[i] != NWAM_ADDRSRC_AUTOCONF)
1647 return (NWAM_ENTITY_INVALID_VALUE);
1648 if (addrsrc[i] == NWAM_ADDRSRC_DHCP)
1649 dhcp_found = B_TRUE;
1650 if (addrsrc[i] == NWAM_ADDRSRC_AUTOCONF)
1651 autoconf_found = B_TRUE;
1652 }
1653 /*
1654 * DHCP and AUTOCONF need to be specified as v6 address sources
1655 * since there is no way to switch them off in NWAM at present.
1656 */
1657 if (dhcp_found && autoconf_found)
1658 return (NWAM_SUCCESS);
1659 else
1660 return (NWAM_ENTITY_INVALID_VALUE);
1661 }
1662
1663 static nwam_error_t
valid_reqhost(nwam_value_t value)1664 valid_reqhost(nwam_value_t value)
1665 {
1666 char *hostname;
1667
1668 if (nwam_value_get_string(value, &hostname) != NWAM_SUCCESS)
1669 return (NWAM_ENTITY_INVALID_VALUE);
1670 return (ipadm_is_valid_hostname(hostname) ? NWAM_SUCCESS
1671 : NWAM_ENTITY_INVALID_VALUE);
1672 }
1673
1674 /* ARGSUSED0 */
1675 static nwam_error_t
valid_link_mtu(nwam_value_t value)1676 valid_link_mtu(nwam_value_t value)
1677 {
1678 return (NWAM_SUCCESS);
1679 }
1680
1681 nwam_error_t
nwam_ncu_validate(nwam_ncu_handle_t ncuh,const char ** errpropp)1682 nwam_ncu_validate(nwam_ncu_handle_t ncuh, const char **errpropp)
1683 {
1684 return (nwam_validate(ncu_prop_table, ncuh, errpropp));
1685 }
1686
1687 /*
1688 * Given the ncu type and ncu class, return the list of properties that needs
1689 * to be set. Note this list is a complete property list that includes both
1690 * the required ones and the optional ones. Caller needs to free prop_list.
1691 */
1692 nwam_error_t
nwam_ncu_get_default_proplist(nwam_ncu_type_t type,nwam_ncu_class_t class,const char *** prop_list,uint_t * numvalues)1693 nwam_ncu_get_default_proplist(nwam_ncu_type_t type, nwam_ncu_class_t class,
1694 const char ***prop_list, uint_t *numvalues)
1695 {
1696 uint64_t typeflags = nwam_ncu_type_to_flag(type);
1697 uint64_t classflags = nwam_ncu_class_to_flag(class);
1698
1699 return (nwam_get_default_proplist(ncu_prop_table, typeflags,
1700 classflags, prop_list, numvalues));
1701 }
1702
1703 nwam_error_t
nwam_ncp_get_state(nwam_ncp_handle_t ncph,nwam_state_t * statep,nwam_aux_state_t * auxp)1704 nwam_ncp_get_state(nwam_ncp_handle_t ncph, nwam_state_t *statep,
1705 nwam_aux_state_t *auxp)
1706 {
1707 return (nwam_get_state(ncph->nwh_name, ncph, statep, auxp));
1708 }
1709
1710 nwam_error_t
nwam_ncu_get_state(nwam_ncu_handle_t ncuh,nwam_state_t * statep,nwam_aux_state_t * auxp)1711 nwam_ncu_get_state(nwam_ncu_handle_t ncuh, nwam_state_t *statep,
1712 nwam_aux_state_t *auxp)
1713 {
1714 nwam_ncp_handle_t ncph;
1715 char *ncpname;
1716 nwam_error_t err;
1717
1718 assert(ncuh != NULL);
1719
1720 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
1721 return (err);
1722 if (!nwam_ncp_is_active(ncph)) {
1723 nwam_ncp_free(ncph);
1724 return (NWAM_ENTITY_INVALID);
1725 }
1726 nwam_ncp_free(ncph);
1727
1728 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1729 != NWAM_SUCCESS)
1730 return (err);
1731
1732 err = nwam_request_state(NWAM_OBJECT_TYPE_NCU, ncuh->nwh_name, ncpname,
1733 statep, auxp);
1734 free(ncpname);
1735 return (err);
1736 }
1737
1738 nwam_error_t
nwam_ncp_get_active_priority_group(int64_t * priorityp)1739 nwam_ncp_get_active_priority_group(int64_t *priorityp)
1740 {
1741 return (nwam_request_active_priority_group(priorityp));
1742 }
1743