1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <assert.h>
28 #include <ctype.h>
29 #include <libgen.h>
30 #include <netdb.h>
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <libdladm.h>
42
43 #include "libnwam_impl.h"
44 #include <libnwam_priv.h>
45 #include <libnwam.h>
46
47 /*
48 * Functions to support creating, modifying, destroying, querying the
49 * state of and changing the state of NCP (Network Configuration Profiles)
50 * and the NCUs (Network Configuration Units) that are contained in those
51 * NCP objects. An NCP is simply a container for a set of NCUs which represent
52 * the datalink and interface configuration preferences for the system.
53 * An NCP can consist a set of prioritized link NCUs, e.g. wired links preferred
54 * over wireless, a set of manually enabled/diasbled NCUs, or a combination
55 * of both. Interface NCUs inherit activation from their underlying links,
56 * so if wired is preferred over wireless and a cable is plugged in,
57 * the wired link NCU will be active, as will the IP interface NCU above it.
58 */
59
60 /*
61 * The NCU property table is used to mapping property types to property name
62 * strings, their associated value types etc. The table is used for validation
63 * purposes, and for commit()ing and read()ing NCUs.
64 */
65
66 static nwam_error_t valid_type(nwam_value_t);
67 static nwam_error_t valid_class(nwam_value_t);
68 static nwam_error_t valid_ncp(nwam_value_t);
69 static nwam_error_t valid_priority_mode(nwam_value_t);
70 static nwam_error_t valid_ncu_activation_mode(nwam_value_t);
71 static nwam_error_t valid_link_autopush(nwam_value_t);
72 static nwam_error_t valid_link_mtu(nwam_value_t);
73 static nwam_error_t valid_ip_version(nwam_value_t);
74 static nwam_error_t valid_addrsrc_v4(nwam_value_t);
75 static nwam_error_t valid_addrsrc_v6(nwam_value_t);
76
77 struct nwam_prop_table_entry ncu_prop_table_entries[] = {
78 {NWAM_NCU_PROP_TYPE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1, valid_type,
79 "specifies the NCU type - valid values are \'datalink\' and \'ip\'",
80 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
81 {NWAM_NCU_PROP_CLASS, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
82 valid_class,
83 "specifies the NCU class - valid values are "
84 "\'phys\' and \'ip\'",
85 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
86 {NWAM_NCU_PROP_PARENT_NCP, NWAM_VALUE_TYPE_STRING, B_FALSE, 1, 1,
87 valid_ncp,
88 "specifies the parent NCP name",
89 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
90 {NWAM_NCU_PROP_ACTIVATION_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 1, 1,
91 valid_ncu_activation_mode,
92 "specifies the NCU activation mode - valid values are:\n"
93 "\'prioritized\' and \'manual\'",
94 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
95 {NWAM_NCU_PROP_ENABLED, NWAM_VALUE_TYPE_BOOLEAN, B_TRUE, 0, 1,
96 nwam_valid_boolean,
97 "specifies if manual NCU is to be enabled",
98 NWAM_FLAG_NCU_TYPE_ALL, NWAM_FLAG_NCU_CLASS_ALL},
99 {NWAM_NCU_PROP_PRIORITY_GROUP, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
100 nwam_valid_uint64,
101 "specifies the priority grouping of NCUs - lower values are "
102 "prioritized, negative values are invalid",
103 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
104 {NWAM_NCU_PROP_PRIORITY_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
105 valid_priority_mode,
106 "specifies the mode of prioritization - valid values are:\n"
107 "\'exclusive\', \'shared\' and \'all\'",
108 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
109 {NWAM_NCU_PROP_LINK_MAC_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0, 1,
110 nwam_valid_mac_addr,
111 "specifies MAC address of form aa:bb:cc:dd:ee:ff for the link",
112 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
113 {NWAM_NCU_PROP_LINK_AUTOPUSH, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
114 NWAM_MAX_NUM_VALUES, valid_link_autopush,
115 "specifies modules to autopush on link",
116 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
117 {NWAM_NCU_PROP_LINK_MTU, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0, 1,
118 valid_link_mtu,
119 "specifies MTU for link",
120 NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_CLASS_ALL_LINK},
121 {NWAM_NCU_PROP_IP_VERSION, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
122 NWAM_MAX_NUM_VALUES, valid_ip_version,
123 "specifies IP versions for IP NCU - valid values are:\n"
124 "\'ipv4\' and \'ipv6\'",
125 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
126 {NWAM_NCU_PROP_IPV4_ADDRSRC, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
127 NWAM_MAX_NUM_VALUES, valid_addrsrc_v4,
128 "specifies IPv4 address source(s) - valid values are:\n"
129 "\'dhcp\' and \'static\'",
130 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
131 {NWAM_NCU_PROP_IPV4_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
132 NWAM_MAX_NUM_VALUES, nwam_valid_host_v4,
133 "specifies static IPv4 host address(es)",
134 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
135 {NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
136 1, nwam_valid_route_v4,
137 "specifies per-interface default IPv4 route",
138 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
139 {NWAM_NCU_PROP_IPV6_ADDRSRC, NWAM_VALUE_TYPE_UINT64, B_FALSE, 0,
140 NWAM_MAX_NUM_VALUES, valid_addrsrc_v6,
141 "specifies IPv6 address source(s) - valid values are:\n"
142 "\'dhcp\', \'autoconf\' and \'static\'.\n"
143 "\'dhcp\' and \'autoconf\' are mandatory values.",
144 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
145 {NWAM_NCU_PROP_IPV6_ADDR, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
146 NWAM_MAX_NUM_VALUES, nwam_valid_host_v6,
147 "specifies static IPv6 host address(es)",
148 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE},
149 {NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE, NWAM_VALUE_TYPE_STRING, B_FALSE, 0,
150 1, nwam_valid_route_v6,
151 "specifies per-interface default IPv6 route",
152 NWAM_FLAG_NCU_TYPE_INTERFACE, NWAM_FLAG_NCU_CLASS_ALL_INTERFACE}
153 };
154
155 #define NWAM_NUM_NCU_PROPS (sizeof (ncu_prop_table_entries) / \
156 sizeof (*ncu_prop_table_entries))
157
158 struct nwam_prop_table ncu_prop_table =
159 { NWAM_NUM_NCU_PROPS, ncu_prop_table_entries };
160
161 nwam_error_t
nwam_ncp_get_name(nwam_ncp_handle_t ncph,char ** namep)162 nwam_ncp_get_name(nwam_ncp_handle_t ncph, char **namep)
163 {
164 return (nwam_get_name(ncph, namep));
165 }
166
167 static nwam_error_t
nwam_ncp_name_to_file(const char * name,char ** filename)168 nwam_ncp_name_to_file(const char *name, char **filename)
169 {
170 assert(name != NULL && filename != NULL);
171
172 if ((*filename = malloc(MAXPATHLEN)) == NULL)
173 return (NWAM_NO_MEMORY);
174
175 (void) snprintf(*filename, MAXPATHLEN, "%s%s%s%s", NWAM_CONF_DIR,
176 NWAM_NCP_CONF_FILE_PRE, name, NWAM_NCP_CONF_FILE_SUF);
177
178 return (NWAM_SUCCESS);
179 }
180
181 /* ARGSUSED1 */
182 nwam_error_t
nwam_ncp_create(const char * name,uint64_t flags,nwam_ncp_handle_t * ncphp)183 nwam_ncp_create(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
184 {
185 nwam_error_t err;
186 char *ncpfile;
187
188 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, name, ncphp))
189 != NWAM_SUCCESS)
190 return (err);
191
192 /* Create empty container for NCUs */
193 if ((err = nwam_ncp_name_to_file(name, &ncpfile))
194 != NWAM_SUCCESS) {
195 nwam_free(*ncphp);
196 *ncphp = NULL;
197 return (err);
198 }
199
200 if ((err = nwam_commit(ncpfile, *ncphp, flags)) != NWAM_SUCCESS) {
201 nwam_free(*ncphp);
202 *ncphp = NULL;
203 }
204
205 free(ncpfile);
206
207 return (err);
208 }
209
210 /* Used by libnwam_files.c */
211 nwam_error_t
nwam_ncp_file_to_name(const char * path,char ** name)212 nwam_ncp_file_to_name(const char *path, char **name)
213 {
214 char path_copy[MAXPATHLEN];
215 char *filename, *suffix;
216
217 assert(path != NULL && name != NULL);
218
219 /* Make a copy as basename(3c) may modify string */
220 (void) strlcpy(path_copy, path, MAXPATHLEN);
221
222 if ((*name = malloc(NWAM_MAX_NAME_LEN)) == NULL)
223 return (NWAM_NO_MEMORY);
224
225 if ((filename = basename(path_copy)) == NULL) {
226 free(*name);
227 return (NWAM_ENTITY_INVALID);
228 }
229
230 /* Ensure filename begins/ends with right prefix/suffix */
231 if (sscanf(filename, NWAM_NCP_CONF_FILE_PRE "%256[^\n]s", *name) < 1) {
232 free(*name);
233 return (NWAM_ENTITY_INVALID);
234 }
235 suffix = *name + strlen(*name) - strlen(NWAM_NCP_CONF_FILE_SUF);
236 if (strstr(*name, NWAM_NCP_CONF_FILE_SUF) != suffix) {
237 free(*name);
238 return (NWAM_ENTITY_INVALID);
239 }
240 suffix[0] = '\0';
241
242 return (NWAM_SUCCESS);
243 }
244
245 /* ARGSUSED1 */
246 nwam_error_t
nwam_ncp_read(const char * name,uint64_t flags,nwam_ncp_handle_t * ncphp)247 nwam_ncp_read(const char *name, uint64_t flags, nwam_ncp_handle_t *ncphp)
248 {
249 char *filename;
250 nwam_error_t err;
251
252 assert(name != NULL && ncphp != NULL);
253
254 /* try to read the associated ncp configuration */
255 if ((err = nwam_ncp_name_to_file(name, &filename)) != NWAM_SUCCESS) {
256 *ncphp = NULL;
257 return (err);
258 }
259
260 err = nwam_read(NWAM_OBJECT_TYPE_NCP, filename, name, flags, ncphp);
261 free(filename);
262 return (err);
263 }
264
265 static nwam_error_t
nwam_ncu_get_parent_ncp_name(nwam_ncu_handle_t ncuh,char ** parentnamep)266 nwam_ncu_get_parent_ncp_name(nwam_ncu_handle_t ncuh, char **parentnamep)
267 {
268 nwam_value_t parentval = NULL;
269 char *parentname;
270 nwam_error_t err;
271
272 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_PARENT_NCP,
273 &parentval)) != NWAM_SUCCESS ||
274 (err = nwam_value_get_string(parentval, &parentname))
275 != NWAM_SUCCESS ||
276 (*parentnamep = strdup(parentname)) == NULL) {
277 if (parentval != NULL)
278 nwam_value_free(parentval);
279 *parentnamep = NULL;
280 return (err);
281 }
282 nwam_value_free(parentval);
283
284 return (NWAM_SUCCESS);
285 }
286
287 static int
nwam_ncp_copy_callback(nwam_ncu_handle_t oldncuh,void * arg)288 nwam_ncp_copy_callback(nwam_ncu_handle_t oldncuh, void *arg)
289 {
290 nwam_error_t err;
291 nwam_ncu_handle_t newncuh = NULL;
292 char *oldparent;
293 char *oldfilename = NULL, *newfilename = NULL;
294 nwam_ncp_handle_t newncph = (nwam_ncp_handle_t)arg;
295 nwam_value_t newparentval;
296
297 /* Get filenames for the new and old NCU's */
298 if ((err = nwam_ncu_get_parent_ncp_name(oldncuh, &oldparent))
299 != NWAM_SUCCESS)
300 return (err);
301 err = nwam_ncp_name_to_file(oldparent, &oldfilename);
302 free(oldparent);
303 if (err != NWAM_SUCCESS)
304 return (err);
305 if ((err = nwam_ncp_name_to_file(newncph->nwh_name, &newfilename))
306 != NWAM_SUCCESS)
307 goto fail;
308
309 /* new NCU name (and typedname) is the same as the old name */
310 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, oldncuh->nwh_name,
311 &newncuh)) != NWAM_SUCCESS)
312 goto fail;
313 /* Duplicate the old NCU's data */
314 if ((err = nwam_dup_object_list(oldncuh->nwh_data,
315 &(newncuh->nwh_data))) != NWAM_SUCCESS)
316 goto fail;
317
318 /* Update the parent property for the new NCU */
319 if ((err = nwam_value_create_string(newncph->nwh_name, &newparentval))
320 != NWAM_SUCCESS)
321 goto fail;
322 err = nwam_set_prop_value(newncuh->nwh_data, NWAM_NCU_PROP_PARENT_NCP,
323 newparentval);
324 nwam_value_free(newparentval);
325 if (err != NWAM_SUCCESS)
326 goto fail;
327
328 /* Save the new NCU */
329 err = nwam_commit(newfilename, newncuh, 0);
330
331 fail:
332 free(oldfilename);
333 free(newfilename);
334 nwam_ncu_free(newncuh);
335 return (err);
336 }
337
338 nwam_error_t
nwam_ncp_copy(nwam_ncp_handle_t oldncph,const char * newname,nwam_ncp_handle_t * newncphp)339 nwam_ncp_copy(nwam_ncp_handle_t oldncph, const char *newname,
340 nwam_ncp_handle_t *newncphp)
341 {
342 nwam_ncp_handle_t ncph;
343 nwam_error_t err;
344 int cb_ret;
345
346 assert(oldncph != NULL && newname != NULL && newncphp != NULL);
347
348 /* check if newname NCP already exists */
349 if (nwam_ncp_read(newname, 0, &ncph) == NWAM_SUCCESS) {
350 nwam_ncp_free(ncph);
351 *newncphp = NULL;
352 return (NWAM_ENTITY_EXISTS);
353 }
354
355 /* create new handle */
356 if ((err = nwam_ncp_create(newname, 0, newncphp)) != NWAM_SUCCESS)
357 return (err);
358
359 err = nwam_ncp_walk_ncus(oldncph, nwam_ncp_copy_callback, *newncphp,
360 NWAM_FLAG_NCU_TYPE_CLASS_ALL, &cb_ret);
361 if (err != NWAM_SUCCESS) {
362 /* remove the NCP even if any NCU's had already been copied */
363 (void) nwam_ncp_destroy(*newncphp, 0);
364 *newncphp = NULL;
365 if (err == NWAM_WALK_HALTED)
366 return (cb_ret);
367 else
368 return (err);
369 }
370
371 return (NWAM_SUCCESS);
372 }
373
374 /*
375 * Convert type to flag
376 */
377 static uint64_t
nwam_ncu_type_to_flag(nwam_ncu_type_t type)378 nwam_ncu_type_to_flag(nwam_ncu_type_t type)
379 {
380 switch (type) {
381 case NWAM_NCU_TYPE_LINK:
382 return (NWAM_FLAG_NCU_TYPE_LINK);
383 case NWAM_NCU_TYPE_INTERFACE:
384 return (NWAM_FLAG_NCU_TYPE_INTERFACE);
385 case NWAM_NCU_TYPE_ANY:
386 return (NWAM_FLAG_NCU_TYPE_ALL);
387 default:
388 return (0);
389 }
390 }
391
392 /*
393 * Convert class to flag
394 */
395 uint64_t
nwam_ncu_class_to_flag(nwam_ncu_class_t class)396 nwam_ncu_class_to_flag(nwam_ncu_class_t class)
397 {
398 switch (class) {
399 case NWAM_NCU_CLASS_PHYS:
400 return (NWAM_FLAG_NCU_CLASS_PHYS);
401 case NWAM_NCU_CLASS_IP:
402 return (NWAM_FLAG_NCU_CLASS_IP);
403 case NWAM_NCU_CLASS_ANY:
404 return (NWAM_FLAG_NCU_CLASS_ALL);
405 default:
406 return (0);
407 }
408 }
409
410 /*
411 * Infer NCU type from NCU class
412 */
413 nwam_ncu_type_t
nwam_ncu_class_to_type(nwam_ncu_class_t class)414 nwam_ncu_class_to_type(nwam_ncu_class_t class)
415 {
416 switch (class) {
417 case NWAM_NCU_CLASS_PHYS:
418 return (NWAM_NCU_TYPE_LINK);
419 case NWAM_NCU_CLASS_IP:
420 return (NWAM_NCU_TYPE_INTERFACE);
421 case NWAM_NCU_CLASS_ANY:
422 return (NWAM_NCU_TYPE_ANY);
423 default:
424 return (NWAM_NCU_TYPE_UNKNOWN);
425 }
426 }
427
428 /*
429 * Make ncp active, deactivating any other active ncp.
430 */
431 nwam_error_t
nwam_ncp_enable(nwam_ncp_handle_t ncph)432 nwam_ncp_enable(nwam_ncp_handle_t ncph)
433 {
434 nwam_error_t err;
435 char *name;
436
437 assert(ncph != NULL);
438
439 err = nwam_enable(NULL, ncph);
440
441 if (err == NWAM_ERROR_BIND) {
442 /*
443 * nwamd is not running, set active_ncp property so when
444 * nwamd is next started, this NCP will be used.
445 */
446 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
447 return (err);
448
449 err = nwam_set_smf_string_property(NWAM_FMRI, NWAM_PG,
450 NWAM_PROP_ACTIVE_NCP, name);
451 free(name);
452 }
453
454 return (err);
455 }
456
457 /* Compare NCP names c1 and c2 using strcasecmp() */
458 static int
ncpname_cmp(const void * c1,const void * c2)459 ncpname_cmp(const void *c1, const void *c2)
460 {
461 return (strcasecmp(*(const char **)c1, *(const char **)c2));
462 }
463
464 /* ARGSUSED1 */
465 nwam_error_t
nwam_walk_ncps(int (* cb)(nwam_ncp_handle_t,void *),void * data,uint64_t flags,int * retp)466 nwam_walk_ncps(int (*cb)(nwam_ncp_handle_t, void *), void *data,
467 uint64_t flags, int *retp)
468 {
469 char *ncpname, **ncpfiles;
470 nwam_ncp_handle_t ncph;
471 nwam_error_t err;
472 nwam_value_t value;
473 void *objlist;
474 uint_t i, num_ncpfiles;
475 int ret = 0;
476
477 assert(cb != NULL);
478
479 if ((err = nwam_valid_flags(flags, NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
480 return (err);
481 /*
482 * To get list of NCP files, call nwam_read_object_from_backend()
483 * with "parent" argument set to NULL. We get back an object list
484 * consisting of string arrays for each object type - NCP, ENM
485 * and location. We retrieve the NCP list, which corresponds to
486 * the set of NCP backend parent objects (these are files at present).
487 */
488 if ((err = nwam_read_object_from_backend(NULL, NULL, flags,
489 &objlist)) != NWAM_SUCCESS)
490 return (err);
491
492 if ((err = nwam_get_prop_value(objlist, NWAM_NCP_OBJECT_STRING, &value))
493 != NWAM_SUCCESS) {
494 nwam_free_object_list(objlist);
495 return (err);
496 }
497 if ((err = nwam_value_get_string_array(value, &ncpfiles,
498 &num_ncpfiles)) != NWAM_SUCCESS) {
499 nwam_value_free(value);
500 nwam_free_object_list(objlist);
501 return (err);
502 }
503
504 /* sort the NCP names alphabetically */
505 qsort(ncpfiles, num_ncpfiles, sizeof (char *), ncpname_cmp);
506
507 for (i = 0; i < num_ncpfiles; i++) {
508 if (nwam_ncp_file_to_name(ncpfiles[i], &ncpname)
509 != NWAM_SUCCESS)
510 continue;
511 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, ncpname,
512 &ncph)) != NWAM_SUCCESS) {
513 free(ncpname);
514 break;
515 }
516 ret = cb(ncph, data);
517 free(ncph);
518 free(ncpname);
519 if (ret != 0) {
520 err = NWAM_WALK_HALTED;
521 break;
522 }
523 }
524 nwam_value_free(value);
525 nwam_free_object_list(objlist);
526
527 if (retp != NULL)
528 *retp = ret;
529 return (err);
530 }
531
532 /*
533 * Checks if NCP is read-only. Only NWAM_NCP_NAME_AUTOMATIC is read-only
534 * for all but the netadm user (which nwamd runs as).
535 */
536 nwam_error_t
nwam_ncp_get_read_only(nwam_ncp_handle_t ncph,boolean_t * readp)537 nwam_ncp_get_read_only(nwam_ncp_handle_t ncph, boolean_t *readp)
538 {
539 nwam_error_t err;
540 char *name;
541
542 assert(ncph != NULL && readp != NULL);
543
544 if ((err = nwam_ncp_get_name(ncph, &name)) != NWAM_SUCCESS)
545 return (err);
546
547 if (NWAM_NCP_AUTOMATIC(name))
548 *readp = !nwam_uid_is_special();
549 else
550 *readp = B_FALSE;
551
552 free(name);
553 return (NWAM_SUCCESS);
554 }
555
556 /* Checks if NCU is writable depending on its parent */
557 nwam_error_t
nwam_ncu_get_read_only(nwam_ncu_handle_t ncuh,boolean_t * readp)558 nwam_ncu_get_read_only(nwam_ncu_handle_t ncuh, boolean_t *readp)
559 {
560 nwam_error_t err;
561 nwam_ncp_handle_t ncph;
562
563 assert(ncuh != NULL && readp != NULL);
564
565 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
566 return (err);
567
568 err = nwam_ncp_get_read_only(ncph, readp);
569 nwam_ncp_free(ncph);
570 return (err);
571 }
572
573 /* Returns true if the NCP is active */
574 static boolean_t
nwam_ncp_is_active(nwam_ncp_handle_t ncph)575 nwam_ncp_is_active(nwam_ncp_handle_t ncph)
576 {
577 char *active_ncp, *name;
578 boolean_t ret;
579
580 assert(ncph != NULL);
581
582 /*
583 * Determine which NCP is active via the nwamd/active_ncp property
584 * value. This allows us to determine which NCP is active even
585 * if nwamd is not running.
586 */
587 if (nwam_ncp_get_name(ncph, &name) != NWAM_SUCCESS ||
588 nwam_get_smf_string_property(NWAM_FMRI, NWAM_PG,
589 NWAM_PROP_ACTIVE_NCP, &active_ncp) != NWAM_SUCCESS)
590 return (B_FALSE);
591
592 ret = (strcmp(name, active_ncp) == 0);
593
594 free(active_ncp);
595 free(name);
596
597 return (ret);
598 }
599
600 nwam_error_t
nwam_ncp_destroy(nwam_ncp_handle_t ncph,uint64_t flags)601 nwam_ncp_destroy(nwam_ncp_handle_t ncph, uint64_t flags)
602 {
603 char *filename;
604 nwam_error_t err;
605 boolean_t read_only;
606
607 assert(ncph != NULL);
608
609 if ((err = nwam_ncp_get_read_only(ncph, &read_only)) != NWAM_SUCCESS)
610 return (err);
611 if (read_only)
612 return (NWAM_ENTITY_NOT_DESTROYABLE);
613
614 if (nwam_ncp_is_active(ncph))
615 return (NWAM_ENTITY_IN_USE);
616
617 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &filename))
618 != NWAM_SUCCESS)
619 return (err);
620
621 err = nwam_destroy(filename, ncph, flags);
622 free(filename);
623
624 return (NWAM_SUCCESS);
625 }
626
627 static nwam_error_t
nwam_ncu_internal_name_to_name(const char * internalname,nwam_ncu_type_t * typep,char ** namep)628 nwam_ncu_internal_name_to_name(const char *internalname,
629 nwam_ncu_type_t *typep, char **namep)
630 {
631 char *prefixstr;
632
633 assert(internalname != NULL && namep != NULL);
634
635 if (strncasecmp(internalname, NWAM_NCU_LINK_NAME_PRE,
636 strlen(NWAM_NCU_LINK_NAME_PRE)) == 0) {
637 prefixstr = NWAM_NCU_LINK_NAME_PRE;
638 *typep = NWAM_NCU_TYPE_LINK;
639 } else if (strncasecmp(internalname, NWAM_NCU_INTERFACE_NAME_PRE,
640 strlen(NWAM_NCU_INTERFACE_NAME_PRE)) == 0) {
641 prefixstr = NWAM_NCU_INTERFACE_NAME_PRE;
642 *typep = NWAM_NCU_TYPE_INTERFACE;
643 } else {
644 return (NWAM_INVALID_ARG);
645 }
646
647 *namep = strdup(internalname + strlen(prefixstr));
648 if (*namep == NULL)
649 return (NWAM_NO_MEMORY);
650 return (NWAM_SUCCESS);
651 }
652
653 /* ARGSUSED2 */
654 static int
ncu_selectcb(struct nwam_handle * hp,uint64_t flags,void * data)655 ncu_selectcb(struct nwam_handle *hp, uint64_t flags, void *data)
656 {
657 nwam_ncu_handle_t ncuh = hp;
658 nwam_value_t typeval = NULL, classval = NULL;
659 uint64_t type, class, matchflags, walkfilter;
660
661 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval)
662 != NWAM_SUCCESS ||
663 nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS, &classval)
664 != NWAM_SUCCESS) {
665 if (typeval != NULL)
666 nwam_value_free(typeval);
667 return (NWAM_INVALID_ARG);
668 }
669 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS ||
670 nwam_value_get_uint64(classval, &class) != NWAM_SUCCESS) {
671 nwam_value_free(typeval);
672 nwam_value_free(classval);
673 return (NWAM_INVALID_ARG);
674 }
675
676 matchflags = nwam_ncu_type_to_flag(type) |
677 nwam_ncu_class_to_flag(class);
678 nwam_value_free(typeval);
679 nwam_value_free(classval);
680
681 if ((walkfilter = (flags & NWAM_WALK_FILTER_MASK)) == 0)
682 walkfilter = NWAM_FLAG_NCU_TYPE_CLASS_ALL;
683
684 if (matchflags & walkfilter)
685 return (NWAM_SUCCESS);
686 return (NWAM_INVALID_ARG);
687 }
688
689 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)690 nwam_ncp_walk_ncus(nwam_ncp_handle_t ncph,
691 int(*cb)(nwam_ncu_handle_t, void *), void *data, uint64_t flags, int *retp)
692 {
693 char *ncpfile;
694 nwam_error_t err;
695
696 assert(ncph != NULL && cb != NULL);
697
698 if ((err = nwam_valid_flags(flags,
699 NWAM_FLAG_NCU_TYPE_CLASS_ALL | NWAM_FLAG_BLOCKING)) != NWAM_SUCCESS)
700 return (err);
701
702 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
703 != NWAM_SUCCESS)
704 return (err);
705
706 err = nwam_walk(NWAM_OBJECT_TYPE_NCU, ncpfile, cb, data, flags,
707 retp, ncu_selectcb);
708 free(ncpfile);
709
710 return (err);
711 }
712
713 void
nwam_ncp_free(nwam_ncp_handle_t ncph)714 nwam_ncp_free(nwam_ncp_handle_t ncph)
715 {
716 nwam_free(ncph);
717 }
718
719 /*
720 * Are ncu type and class compatible?
721 */
722 static boolean_t
nwam_ncu_type_class_compatible(nwam_ncu_type_t type,nwam_ncu_class_t class)723 nwam_ncu_type_class_compatible(nwam_ncu_type_t type, nwam_ncu_class_t class)
724 {
725 switch (type) {
726 case NWAM_NCU_TYPE_LINK:
727 return (class == NWAM_NCU_CLASS_PHYS);
728 case NWAM_NCU_TYPE_INTERFACE:
729 return (class == NWAM_NCU_CLASS_IP);
730 default:
731 return (B_FALSE);
732 }
733 }
734
735 /* Name to validate may be internal name. If so, convert it before validating */
736 static boolean_t
valid_ncu_name(const char * name)737 valid_ncu_name(const char *name)
738 {
739 char *n;
740 boolean_t ret;
741 nwam_ncu_type_t type;
742
743 if (nwam_ncu_internal_name_to_name(name, &type, &n) == NWAM_SUCCESS) {
744
745 ret = dladm_valid_linkname(n);
746 free(n);
747 } else {
748 ret = dladm_valid_linkname(name);
749 }
750
751 return (ret);
752 }
753
754 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)755 nwam_ncu_create(nwam_ncp_handle_t ncph, const char *name,
756 nwam_ncu_type_t type, nwam_ncu_class_t class, nwam_ncu_handle_t *ncuhp)
757 {
758 nwam_ncu_handle_t ncuh;
759 nwam_value_t typeval = NULL, classval = NULL, parentval = NULL;
760 nwam_value_t enabledval = NULL;
761 nwam_error_t err;
762 boolean_t read_only;
763 char *typedname;
764
765 assert(ncph != NULL && name != NULL && ncuhp != NULL);
766
767 if (!valid_ncu_name(name))
768 return (NWAM_INVALID_ARG);
769
770 if ((err = nwam_ncp_get_read_only(ncph, &read_only)) != NWAM_SUCCESS)
771 return (err);
772 if (read_only)
773 return (NWAM_ENTITY_READ_ONLY);
774
775 if (nwam_ncu_read(ncph, name, type, 0, &ncuh) == NWAM_SUCCESS) {
776 nwam_ncu_free(ncuh);
777 return (NWAM_ENTITY_EXISTS);
778 }
779
780 if (!valid_ncu_name(name) ||
781 !nwam_ncu_type_class_compatible(type, class))
782 return (NWAM_INVALID_ARG);
783
784 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname))
785 != NWAM_SUCCESS)
786 return (err);
787
788 /* Create handle */
789 if ((err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, typedname, ncuhp))
790 != NWAM_SUCCESS)
791 return (err);
792 free(typedname);
793
794 /*
795 * Create new object list for NCU. The new NCU is initialized with
796 * the appropriate type and class.
797 */
798 if ((err = nwam_alloc_object_list(&(*ncuhp)->nwh_data)) != NWAM_SUCCESS)
799 goto finish;
800
801 if ((err = nwam_value_create_uint64(type, &typeval))
802 != NWAM_SUCCESS ||
803 (err = nwam_value_create_uint64(class, &classval))
804 != NWAM_SUCCESS ||
805 (err = nwam_value_create_string(ncph->nwh_name, &parentval))
806 != NWAM_SUCCESS ||
807 (err = nwam_value_create_boolean(B_TRUE, &enabledval))
808 != NWAM_SUCCESS) {
809 goto finish;
810 }
811 if ((err = nwam_set_prop_value((*ncuhp)->nwh_data, NWAM_NCU_PROP_TYPE,
812 typeval)) != NWAM_SUCCESS ||
813 (err = nwam_set_prop_value((*ncuhp)->nwh_data, NWAM_NCU_PROP_CLASS,
814 classval)) != NWAM_SUCCESS ||
815 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
816 NWAM_NCU_PROP_PARENT_NCP, parentval)) != NWAM_SUCCESS ||
817 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
818 NWAM_NCU_PROP_ENABLED, enabledval)) != NWAM_SUCCESS) {
819 goto finish;
820 }
821
822 /* Set default IP, datalink properties */
823 if (type == NWAM_NCU_TYPE_INTERFACE && class == NWAM_NCU_CLASS_IP) {
824
825 uint64_t ver[] = { IPV4_VERSION, IPV6_VERSION };
826 uint64_t v6src[] = { NWAM_ADDRSRC_DHCP, NWAM_ADDRSRC_AUTOCONF };
827 uint_t vercnt = 2, v6srccnt = 2;
828 nwam_value_t ipver = NULL, v4addrsrc = NULL, v6addrsrc = NULL;
829
830 if ((err = nwam_value_create_uint64_array(ver, vercnt, &ipver))
831 != NWAM_SUCCESS ||
832 (err = nwam_value_create_uint64(NWAM_ADDRSRC_DHCP,
833 &v4addrsrc)) != NWAM_SUCCESS ||
834 (err = nwam_value_create_uint64_array(v6src, v6srccnt,
835 &v6addrsrc)) != NWAM_SUCCESS) {
836 nwam_value_free(ipver);
837 nwam_value_free(v4addrsrc);
838 goto finish;
839 }
840 if ((err = nwam_set_prop_value((*ncuhp)->nwh_data,
841 NWAM_NCU_PROP_IP_VERSION, ipver)) == NWAM_SUCCESS &&
842 (err = nwam_set_prop_value((*ncuhp)->nwh_data,
843 NWAM_NCU_PROP_IPV4_ADDRSRC, v4addrsrc)) == NWAM_SUCCESS) {
844 err = nwam_set_prop_value((*ncuhp)->nwh_data,
845 NWAM_NCU_PROP_IPV6_ADDRSRC, v6addrsrc);
846 }
847 nwam_value_free(ipver);
848 nwam_value_free(v4addrsrc);
849 nwam_value_free(v6addrsrc);
850 } else {
851 nwam_value_t actval = NULL;
852 if ((err = nwam_value_create_uint64(NWAM_ACTIVATION_MODE_MANUAL,
853 &actval)) != NWAM_SUCCESS)
854 goto finish;
855 err = nwam_set_prop_value((*ncuhp)->nwh_data,
856 NWAM_NCU_PROP_ACTIVATION_MODE, actval);
857 nwam_value_free(actval);
858 }
859
860 finish:
861 nwam_value_free(typeval);
862 nwam_value_free(classval);
863 nwam_value_free(parentval);
864 nwam_value_free(enabledval);
865 if (err != NWAM_SUCCESS) {
866 nwam_ncu_free(*ncuhp);
867 *ncuhp = NULL;
868 }
869 return (err);
870 }
871
872 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)873 nwam_ncu_read(nwam_ncp_handle_t ncph, const char *name,
874 nwam_ncu_type_t type, uint64_t flags, nwam_ncu_handle_t *ncuhp)
875 {
876 char *ncpfile, *typedname;
877 nwam_error_t err, err_ip, err_link;
878 nwam_ncu_handle_t ncuh_ip, ncuh_link;
879
880 assert(ncph != NULL && name != NULL && ncuhp != NULL);
881
882 if ((err = nwam_ncp_name_to_file(ncph->nwh_name, &ncpfile))
883 != NWAM_SUCCESS)
884 return (err);
885
886 if (type == NWAM_NCU_TYPE_ANY) {
887
888 free(ncpfile);
889
890 /*
891 * If we get to this point, we have discovered that no
892 * NCU type is discernable from name or type arguments.
893 * Either exactly one NCU called name must exist of either
894 * type, or the operation should fail.
895 */
896 err_ip = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_INTERFACE,
897 flags, &ncuh_ip);
898 err_link = nwam_ncu_read(ncph, name, NWAM_NCU_TYPE_LINK,
899 flags, &ncuh_link);
900
901 *ncuhp = NULL;
902
903 if (err_ip == NWAM_SUCCESS && err_link == NWAM_SUCCESS) {
904 nwam_ncu_free(ncuh_ip);
905 nwam_ncu_free(ncuh_link);
906 err = NWAM_ENTITY_MULTIPLE_VALUES;
907 } else if (err_ip != NWAM_SUCCESS && err_link != NWAM_SUCCESS) {
908 err = NWAM_ENTITY_NOT_FOUND;
909 } else {
910 if (err_ip == NWAM_SUCCESS) {
911 *ncuhp = ncuh_ip;
912 } else {
913 *ncuhp = ncuh_link;
914 }
915 err = NWAM_SUCCESS;
916 }
917
918 return (err);
919 }
920 if ((err = nwam_ncu_name_to_typed_name(name, type, &typedname)) !=
921 NWAM_SUCCESS) {
922 free(ncpfile);
923 return (err);
924 }
925 err = nwam_read(NWAM_OBJECT_TYPE_NCU, ncpfile, typedname, flags, ncuhp);
926
927 free(typedname);
928 free(ncpfile);
929
930 return (err);
931 }
932
933 nwam_error_t
nwam_ncu_get_name(nwam_ncu_handle_t ncuh,char ** namep)934 nwam_ncu_get_name(nwam_ncu_handle_t ncuh, char **namep)
935 {
936 nwam_ncu_type_t type;
937
938 assert(ncuh != NULL && namep != NULL);
939
940 return (nwam_ncu_internal_name_to_name(ncuh->nwh_name, &type, namep));
941 }
942
943 nwam_error_t
nwam_ncu_name_to_typed_name(const char * name,nwam_ncu_type_t type,char ** typednamep)944 nwam_ncu_name_to_typed_name(const char *name, nwam_ncu_type_t type,
945 char **typednamep)
946 {
947 char *prefixstr;
948 size_t typednamesz;
949
950 assert(name != NULL && typednamep != NULL);
951
952 switch (type) {
953 case NWAM_NCU_TYPE_INTERFACE:
954 prefixstr = NWAM_NCU_INTERFACE_NAME_PRE;
955 break;
956 case NWAM_NCU_TYPE_LINK:
957 prefixstr = NWAM_NCU_LINK_NAME_PRE;
958 break;
959 default:
960 return (NWAM_INVALID_ARG);
961 }
962 typednamesz = strlen(name) + strlen(prefixstr) + 1;
963 if ((*typednamep = malloc(typednamesz)) == NULL)
964 return (NWAM_NO_MEMORY);
965
966 /* Name may be already qualified by type */
967 if (strncasecmp(prefixstr, name, strlen(prefixstr)) == 0) {
968 (void) snprintf(*typednamep, typednamesz, "%s", name);
969 } else {
970 (void) snprintf(*typednamep, typednamesz, "%s%s",
971 prefixstr, name);
972 }
973
974 return (NWAM_SUCCESS);
975 }
976
977 nwam_error_t
nwam_ncu_typed_name_to_name(const char * typed_name,nwam_ncu_type_t * typep,char ** name)978 nwam_ncu_typed_name_to_name(const char *typed_name, nwam_ncu_type_t *typep,
979 char **name)
980 {
981 return (nwam_ncu_internal_name_to_name(typed_name, typep, name));
982 }
983
984 void
nwam_ncu_free(nwam_ncu_handle_t ncuh)985 nwam_ncu_free(nwam_ncu_handle_t ncuh)
986 {
987 nwam_free(ncuh);
988 }
989
990 nwam_error_t
nwam_ncu_copy(nwam_ncu_handle_t oldncuh,const char * newname,nwam_ncu_handle_t * newncuhp)991 nwam_ncu_copy(nwam_ncu_handle_t oldncuh, const char *newname,
992 nwam_ncu_handle_t *newncuhp)
993 {
994 nwam_ncp_handle_t ncph;
995 nwam_ncu_handle_t ncuh;
996 nwam_error_t err;
997 nwam_value_t typeval;
998 uint64_t type;
999 char *typednewname;
1000
1001 assert(oldncuh != NULL && newname != NULL && newncuhp != NULL);
1002
1003 if (nwam_ncu_get_prop_value(oldncuh, NWAM_NCU_PROP_TYPE,
1004 &typeval) != NWAM_SUCCESS) {
1005 return (NWAM_INVALID_ARG);
1006 }
1007 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1008 nwam_value_free(typeval);
1009 return (NWAM_INVALID_ARG);
1010 }
1011 nwam_value_free(typeval);
1012
1013 /* check if newname NCU already exists */
1014 if ((err = nwam_ncu_get_ncp(oldncuh, &ncph)) != NWAM_SUCCESS)
1015 return (err);
1016 if (nwam_ncu_read(ncph, newname, type, 0, &ncuh) == NWAM_SUCCESS) {
1017 nwam_ncu_free(ncuh);
1018 nwam_ncp_free(ncph);
1019 return (NWAM_ENTITY_EXISTS);
1020 }
1021 nwam_ncp_free(ncph);
1022
1023 if ((err = nwam_ncu_name_to_typed_name(newname, type, &typednewname))
1024 != NWAM_SUCCESS)
1025 return (err);
1026
1027 err = nwam_handle_create(NWAM_OBJECT_TYPE_NCU, typednewname, newncuhp);
1028 free(typednewname);
1029 if (err != NWAM_SUCCESS)
1030 return (err);
1031 if ((err = nwam_dup_object_list(oldncuh->nwh_data,
1032 &((*newncuhp)->nwh_data))) != NWAM_SUCCESS) {
1033 free(*newncuhp);
1034 *newncuhp = NULL;
1035 return (err);
1036 }
1037
1038 return (NWAM_SUCCESS);
1039 }
1040
1041 nwam_error_t
nwam_ncu_delete_prop(nwam_ncu_handle_t ncuh,const char * propname)1042 nwam_ncu_delete_prop(nwam_ncu_handle_t ncuh, const char *propname)
1043 {
1044 boolean_t ro_ncu, ro_prop;
1045 nwam_error_t err;
1046 void *olddata;
1047
1048 assert(ncuh != NULL && propname != NULL);
1049
1050 if ((err = nwam_ncu_get_read_only(ncuh, &ro_ncu)) != NWAM_SUCCESS ||
1051 (err = nwam_ncu_prop_read_only(propname, &ro_prop)) != NWAM_SUCCESS)
1052 return (err);
1053 if (ro_ncu || ro_prop)
1054 return (NWAM_ENTITY_READ_ONLY);
1055
1056 /*
1057 * Duplicate data, remove property and validate. If validation
1058 * fails, revert to data duplicated prior to remove.
1059 */
1060 if ((err = nwam_dup_object_list(ncuh->nwh_data, &olddata))
1061 != NWAM_SUCCESS)
1062 return (err);
1063 if ((err = nwam_delete_prop(ncuh->nwh_data, propname))
1064 != NWAM_SUCCESS) {
1065 nwam_free_object_list(ncuh->nwh_data);
1066 ncuh->nwh_data = olddata;
1067 return (err);
1068 }
1069 if ((err = nwam_ncu_validate(ncuh, NULL)) != NWAM_SUCCESS) {
1070 nwam_free_object_list(ncuh->nwh_data);
1071 ncuh->nwh_data = olddata;
1072 return (err);
1073 }
1074 nwam_free_object_list(olddata);
1075
1076 return (NWAM_SUCCESS);
1077 }
1078
1079 nwam_error_t
nwam_ncu_set_prop_value(nwam_ncu_handle_t ncuh,const char * propname,nwam_value_t value)1080 nwam_ncu_set_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1081 nwam_value_t value)
1082 {
1083 boolean_t ro_ncu, ro_prop;
1084 nwam_error_t err;
1085 nwam_ncp_handle_t ncph;
1086
1087 assert(ncuh != NULL && propname != NULL && value != NULL);
1088
1089 if ((err = nwam_ncu_get_read_only(ncuh, &ro_ncu)) != NWAM_SUCCESS ||
1090 (err = nwam_ncu_prop_read_only(propname, &ro_prop)) != NWAM_SUCCESS)
1091 return (err);
1092 if (ro_ncu || ro_prop)
1093 return (NWAM_ENTITY_READ_ONLY);
1094
1095 err = nwam_ncu_get_ncp(ncuh, &ncph);
1096 if (err != NWAM_SUCCESS && err != NWAM_INVALID_ARG) {
1097 /*
1098 * If "parent" property doesn't exist, NWAM_INVALID_ARG
1099 * is returned. Allow the setting to continue.
1100 */
1101 return (err);
1102 }
1103 nwam_ncp_free(ncph);
1104
1105 /* Need to ensure property, type and value are valid */
1106 if ((err = nwam_ncu_validate_prop(ncuh, propname, value))
1107 != NWAM_SUCCESS)
1108 return (err);
1109
1110 return (nwam_set_prop_value(ncuh->nwh_data, propname, value));
1111 }
1112
1113 nwam_error_t
nwam_ncu_get_prop_value(nwam_ncu_handle_t ncuh,const char * propname,nwam_value_t * valuep)1114 nwam_ncu_get_prop_value(nwam_ncu_handle_t ncuh, const char *propname,
1115 nwam_value_t *valuep)
1116 {
1117 assert(ncuh != NULL && propname != NULL && valuep != NULL);
1118
1119 return (nwam_get_prop_value(ncuh->nwh_data, propname, valuep));
1120 }
1121
1122 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)1123 nwam_ncu_walk_props(nwam_ncu_handle_t ncuh,
1124 int (*cb)(const char *, nwam_value_t, void *),
1125 void *data, uint64_t flags, int *retp)
1126 {
1127 return (nwam_walk_props(ncuh, cb, data, flags, retp));
1128 }
1129
1130 nwam_error_t
nwam_ncu_get_ncp(nwam_ncu_handle_t ncuh,nwam_ncp_handle_t * ncphp)1131 nwam_ncu_get_ncp(nwam_ncu_handle_t ncuh, nwam_ncp_handle_t *ncphp)
1132 {
1133 nwam_error_t err;
1134 char *parentname = NULL;
1135
1136 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &parentname))
1137 != NWAM_SUCCESS ||
1138 (err = nwam_handle_create(NWAM_OBJECT_TYPE_NCP, parentname, ncphp))
1139 != NWAM_SUCCESS) {
1140 if (parentname != NULL)
1141 free(parentname);
1142 return (err);
1143 }
1144 free(parentname);
1145
1146 return (NWAM_SUCCESS);
1147 }
1148
1149 nwam_error_t
nwam_ncu_commit(nwam_ncu_handle_t ncuh,uint64_t flags)1150 nwam_ncu_commit(nwam_ncu_handle_t ncuh, uint64_t flags)
1151 {
1152 nwam_error_t err;
1153 boolean_t read_only;
1154 char *ncpfile, *ncpname;
1155
1156 assert(ncuh != NULL && ncuh->nwh_data != NULL);
1157
1158 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1159 return (err);
1160 if (read_only)
1161 return (NWAM_ENTITY_READ_ONLY);
1162
1163 if ((err = nwam_ncu_validate(ncuh, NULL)) != NWAM_SUCCESS ||
1164 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1165 != NWAM_SUCCESS)
1166 return (err);
1167
1168 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile)) != NWAM_SUCCESS) {
1169 free(ncpname);
1170 return (err);
1171 }
1172
1173 err = nwam_commit(ncpfile, ncuh, flags);
1174
1175 free(ncpname);
1176 free(ncpfile);
1177
1178 return (err);
1179 }
1180 /* Get the NCU type */
1181 nwam_error_t
nwam_ncu_get_ncu_type(nwam_ncu_handle_t ncuh,nwam_ncu_type_t * typep)1182 nwam_ncu_get_ncu_type(nwam_ncu_handle_t ncuh, nwam_ncu_type_t *typep)
1183 {
1184 nwam_error_t err;
1185 nwam_value_t typeval;
1186 uint64_t type;
1187
1188 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval))
1189 != NWAM_SUCCESS)
1190 return (err);
1191 err = nwam_value_get_uint64(typeval, &type);
1192 nwam_value_free(typeval);
1193 if (err != NWAM_SUCCESS)
1194 return (err);
1195
1196 *typep = type;
1197 return (NWAM_SUCCESS);
1198 }
1199
1200 /* Get the NCU class */
1201 nwam_error_t
nwam_ncu_get_ncu_class(nwam_ncu_handle_t ncuh,nwam_ncu_class_t * classp)1202 nwam_ncu_get_ncu_class(nwam_ncu_handle_t ncuh, nwam_ncu_class_t *classp)
1203 {
1204 nwam_error_t err;
1205 nwam_value_t classval;
1206 uint64_t class;
1207
1208 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS,
1209 &classval)) != NWAM_SUCCESS)
1210 return (err);
1211 err = nwam_value_get_uint64(classval, &class);
1212 nwam_value_free(classval);
1213 if (err != NWAM_SUCCESS)
1214 return (err);
1215
1216 *classp = class;
1217 return (NWAM_SUCCESS);
1218 }
1219
1220 /*
1221 * Determine if the NCU has manual activation-mode or not.
1222 */
1223 nwam_error_t
nwam_ncu_is_manual(nwam_ncu_handle_t ncuh,boolean_t * manualp)1224 nwam_ncu_is_manual(nwam_ncu_handle_t ncuh, boolean_t *manualp)
1225 {
1226 nwam_error_t err;
1227 nwam_value_t actval;
1228 uint64_t activation;
1229
1230 assert(ncuh != NULL);
1231
1232 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ACTIVATION_MODE,
1233 &actval)) != NWAM_SUCCESS)
1234 return (err);
1235 err = nwam_value_get_uint64(actval, &activation);
1236 nwam_value_free(actval);
1237 if (err != NWAM_SUCCESS)
1238 return (err);
1239
1240 if (activation == NWAM_ACTIVATION_MODE_MANUAL)
1241 *manualp = B_TRUE;
1242 else
1243 *manualp = B_FALSE;
1244 return (NWAM_SUCCESS);
1245 }
1246
1247 /* Determine if NCU is enabled or not */
1248 static nwam_error_t
nwam_ncu_is_enabled(nwam_ncu_handle_t ncuh,boolean_t * enabledp)1249 nwam_ncu_is_enabled(nwam_ncu_handle_t ncuh, boolean_t *enabledp)
1250 {
1251 nwam_error_t err;
1252 nwam_value_t enabledval;
1253
1254 assert(ncuh != NULL);
1255
1256 if ((err = nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_ENABLED,
1257 &enabledval)) != NWAM_SUCCESS)
1258 return (err);
1259 err = nwam_value_get_boolean(enabledval, enabledp);
1260 nwam_value_free(enabledval);
1261 return (err);
1262 }
1263
1264 /* Update the enabled property */
1265 static nwam_error_t
nwam_ncu_update_enabled(nwam_ncu_handle_t ncuh,boolean_t enabled)1266 nwam_ncu_update_enabled(nwam_ncu_handle_t ncuh, boolean_t enabled)
1267 {
1268 nwam_error_t err;
1269 nwam_value_t enabledval;
1270
1271 if ((err = nwam_value_create_boolean(enabled, &enabledval))
1272 != NWAM_SUCCESS)
1273 return (err);
1274 err = nwam_set_prop_value(ncuh->nwh_data, NWAM_NCU_PROP_ENABLED,
1275 enabledval);
1276 nwam_value_free(enabledval);
1277 if (err != NWAM_SUCCESS)
1278 return (err);
1279 return (nwam_ncu_commit(ncuh, NWAM_FLAG_ENTITY_ENABLE));
1280 }
1281
1282 /*
1283 * Make ncu active; fails if the NCU's parent NCP is not active.
1284 */
1285 nwam_error_t
nwam_ncu_enable(nwam_ncu_handle_t ncuh)1286 nwam_ncu_enable(nwam_ncu_handle_t ncuh)
1287 {
1288 char *ncpname = NULL;
1289 nwam_error_t err;
1290 nwam_ncu_type_t type;
1291 boolean_t read_only, enabled, manual;
1292
1293 assert(ncuh != NULL);
1294
1295 /* Don't allow NCUs of Automatic NCP to be enabled */
1296 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1297 return (err);
1298 if (read_only)
1299 return (NWAM_ENTITY_NOT_MANUAL);
1300
1301 /* Link NCUs with manual activation-mode or IP NCUs can be enabled */
1302 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1303 return (err);
1304
1305 if (type == NWAM_NCU_TYPE_LINK) {
1306 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1307 return (err);
1308 if (!manual)
1309 return (NWAM_ENTITY_NOT_MANUAL);
1310 }
1311
1312 /* Make sure NCU is not enabled */
1313 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1314 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1315 != NWAM_SUCCESS)
1316 return (err);
1317
1318 if (enabled) {
1319 free(ncpname);
1320 return (NWAM_SUCCESS);
1321 }
1322
1323 if ((err = nwam_ncu_update_enabled(ncuh, B_TRUE)) != NWAM_SUCCESS) {
1324 free(ncpname);
1325 return (err);
1326 }
1327
1328 err = nwam_enable(ncpname, ncuh);
1329 free(ncpname);
1330
1331 /* nwamd may not be running, that's okay. */
1332 if (err == NWAM_ERROR_BIND)
1333 return (NWAM_SUCCESS);
1334 else
1335 return (err);
1336 }
1337
1338 /*
1339 * Disable ncu; fails if the NCU's parent NCP is not active, or if the
1340 * NCU is not currently active.
1341 */
1342 nwam_error_t
nwam_ncu_disable(nwam_ncu_handle_t ncuh)1343 nwam_ncu_disable(nwam_ncu_handle_t ncuh)
1344 {
1345 char *ncpname = NULL;
1346 nwam_error_t err;
1347 nwam_ncu_type_t type;
1348 boolean_t read_only, enabled, manual;
1349
1350 assert(ncuh != NULL);
1351
1352 /* Don't allow NCUs of Automatic NCP to be disabled */
1353 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1354 return (err);
1355 if (read_only)
1356 return (NWAM_ENTITY_NOT_MANUAL);
1357
1358 /* Link NCUs with manual activation-mode or IP NCUs can be disabled */
1359 if ((err = nwam_ncu_get_ncu_type(ncuh, &type)) != NWAM_SUCCESS)
1360 return (err);
1361
1362 if (type == NWAM_NCU_TYPE_LINK) {
1363 if ((err = nwam_ncu_is_manual(ncuh, &manual)) != NWAM_SUCCESS)
1364 return (err);
1365 if (!manual)
1366 return (NWAM_ENTITY_NOT_MANUAL);
1367 }
1368
1369 /* Make sure NCU is enabled */
1370 if ((err = nwam_ncu_is_enabled(ncuh, &enabled)) != NWAM_SUCCESS ||
1371 (err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1372 != NWAM_SUCCESS)
1373 return (err);
1374
1375 if (!enabled) {
1376 free(ncpname);
1377 return (NWAM_SUCCESS);
1378 }
1379
1380 if ((err = nwam_ncu_update_enabled(ncuh, B_FALSE)) != NWAM_SUCCESS) {
1381 free(ncpname);
1382 return (err);
1383 }
1384
1385 err = nwam_disable(ncpname, ncuh);
1386 free(ncpname);
1387
1388 /* nwamd may not be running, that's okay. */
1389 if (err == NWAM_ERROR_BIND)
1390 return (NWAM_SUCCESS);
1391 else
1392 return (err);
1393 }
1394
1395 nwam_error_t
nwam_ncu_destroy(nwam_ncu_handle_t ncuh,uint64_t flags)1396 nwam_ncu_destroy(nwam_ncu_handle_t ncuh, uint64_t flags)
1397 {
1398 char *ncpname, *ncpfile;
1399 boolean_t read_only;
1400 nwam_error_t err;
1401
1402 assert(ncuh != NULL);
1403
1404 if ((err = nwam_ncu_get_read_only(ncuh, &read_only)) != NWAM_SUCCESS)
1405 return (err);
1406 if (read_only)
1407 return (NWAM_ENTITY_NOT_DESTROYABLE);
1408
1409 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1410 != NWAM_SUCCESS)
1411 return (err);
1412 if ((err = nwam_ncp_name_to_file(ncpname, &ncpfile))
1413 != NWAM_SUCCESS) {
1414 free(ncpname);
1415 return (err);
1416 }
1417
1418 err = nwam_destroy(ncpfile, ncuh, flags);
1419
1420 free(ncpname);
1421 free(ncpfile);
1422
1423 return (err);
1424 }
1425
1426 nwam_error_t
nwam_ncu_get_prop_description(const char * propname,const char ** descriptionp)1427 nwam_ncu_get_prop_description(const char *propname, const char **descriptionp)
1428 {
1429 return (nwam_get_prop_description(ncu_prop_table, propname,
1430 descriptionp));
1431 }
1432
1433 /* Get expected property data type */
1434 nwam_error_t
nwam_ncu_get_prop_type(const char * propname,nwam_value_type_t * typep)1435 nwam_ncu_get_prop_type(const char *propname, nwam_value_type_t *typep)
1436 {
1437 return (nwam_get_prop_type(ncu_prop_table, propname, typep));
1438 }
1439
1440 nwam_error_t
nwam_ncu_prop_read_only(const char * propname,boolean_t * readp)1441 nwam_ncu_prop_read_only(const char *propname, boolean_t *readp)
1442 {
1443 if ((*readp = NWAM_NCU_PROP_SETONCE(propname)) == B_TRUE)
1444 return (NWAM_SUCCESS);
1445
1446 return (nwam_prop_read_only(ncu_prop_table, propname, readp));
1447 }
1448
1449 nwam_error_t
nwam_ncu_prop_multivalued(const char * propname,boolean_t * multip)1450 nwam_ncu_prop_multivalued(const char *propname, boolean_t *multip)
1451 {
1452 return (nwam_prop_multivalued(ncu_prop_table, propname, multip));
1453 }
1454
1455 /*
1456 * Ensure that the properties in the ncu, determined by that ncu's
1457 * type and class, belong there.
1458 */
1459 static nwam_error_t
nwam_ncu_validate_prop_membership(nwam_ncu_handle_t ncuh,const char * propname)1460 nwam_ncu_validate_prop_membership(nwam_ncu_handle_t ncuh, const char *propname)
1461 {
1462 struct nwam_prop_table_entry *pte;
1463 nwam_value_t typeval, classval;
1464 uint64_t type, class;
1465 uint64_t typeflags = 0, classflags = 0;
1466
1467 /* Get type/class from ncu */
1468 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_TYPE, &typeval)
1469 != NWAM_SUCCESS)
1470 return (NWAM_ENTITY_INVALID);
1471 if (nwam_value_get_uint64(typeval, &type) != NWAM_SUCCESS) {
1472 nwam_value_free(typeval);
1473 return (NWAM_ENTITY_INVALID);
1474 }
1475 typeflags = nwam_ncu_type_to_flag((nwam_ncu_type_t)type);
1476 nwam_value_free(typeval);
1477
1478 if (nwam_ncu_get_prop_value(ncuh, NWAM_NCU_PROP_CLASS, &classval)
1479 != NWAM_SUCCESS)
1480 return (NWAM_ENTITY_INVALID);
1481 if (nwam_value_get_uint64(classval, &class) != NWAM_SUCCESS) {
1482 nwam_value_free(classval);
1483 return (NWAM_ENTITY_INVALID);
1484 }
1485 classflags = nwam_ncu_class_to_flag((nwam_ncu_class_t)class);
1486 nwam_value_free(classval);
1487
1488 if ((pte = nwam_get_prop_table_entry(ncu_prop_table, propname)) == NULL)
1489 return (NWAM_INVALID_ARG);
1490
1491 if (typeflags & pte->prop_type_membership &&
1492 classflags & pte->prop_class_membership) {
1493 return (NWAM_SUCCESS);
1494 } else {
1495 return (NWAM_ENTITY_INVALID_MEMBER);
1496 }
1497 }
1498
1499 /* Validate property's ncu membership and type, number and range of values */
1500 nwam_error_t
nwam_ncu_validate_prop(nwam_ncu_handle_t ncuh,const char * propname,nwam_value_t value)1501 nwam_ncu_validate_prop(nwam_ncu_handle_t ncuh, const char *propname,
1502 nwam_value_t value)
1503 {
1504 nwam_error_t err;
1505
1506 assert(ncuh != NULL && propname != NULL);
1507
1508 /* First, determine if this property is valid for this ncu */
1509 if ((err = nwam_ncu_validate_prop_membership(ncuh, propname))
1510 != NWAM_SUCCESS)
1511 return (err);
1512
1513 return (nwam_validate_prop(ncu_prop_table, ncuh, propname, value));
1514 }
1515
1516 /* Property-specific value validation functions follow */
1517
1518 static nwam_error_t
valid_type(nwam_value_t value)1519 valid_type(nwam_value_t value)
1520 {
1521 uint64_t type;
1522
1523 if (nwam_value_get_uint64(value, &type) != NWAM_SUCCESS ||
1524 type > NWAM_NCU_TYPE_INTERFACE)
1525 return (NWAM_ENTITY_INVALID_VALUE);
1526 return (NWAM_SUCCESS);
1527 }
1528
1529 static nwam_error_t
valid_class(nwam_value_t value)1530 valid_class(nwam_value_t value)
1531 {
1532 uint64_t class;
1533
1534 if (nwam_value_get_uint64(value, &class) != NWAM_SUCCESS ||
1535 class > NWAM_NCU_CLASS_IP)
1536 return (NWAM_ENTITY_INVALID_VALUE);
1537 return (NWAM_SUCCESS);
1538 }
1539
1540 static nwam_error_t
valid_ncp(nwam_value_t value)1541 valid_ncp(nwam_value_t value)
1542 {
1543 char *ncp;
1544
1545 if (nwam_value_get_string(value, &ncp) != NWAM_SUCCESS)
1546 return (NWAM_ENTITY_INVALID_VALUE);
1547 return (NWAM_SUCCESS);
1548 }
1549
1550 static nwam_error_t
valid_priority_mode(nwam_value_t value)1551 valid_priority_mode(nwam_value_t value)
1552 {
1553 uint64_t priority_mode;
1554
1555 if (nwam_value_get_uint64(value, &priority_mode) != NWAM_SUCCESS ||
1556 priority_mode > NWAM_PRIORITY_MODE_ALL)
1557 return (NWAM_ENTITY_INVALID_VALUE);
1558 return (NWAM_SUCCESS);
1559 }
1560
1561 static nwam_error_t
valid_ncu_activation_mode(nwam_value_t value)1562 valid_ncu_activation_mode(nwam_value_t value)
1563 {
1564 uint64_t activation_mode;
1565
1566 if (nwam_value_get_uint64(value, &activation_mode) != NWAM_SUCCESS)
1567 return (NWAM_ENTITY_INVALID_VALUE);
1568
1569 switch (activation_mode) {
1570 case NWAM_ACTIVATION_MODE_MANUAL:
1571 case NWAM_ACTIVATION_MODE_PRIORITIZED:
1572 return (NWAM_SUCCESS);
1573 }
1574 return (NWAM_ENTITY_INVALID_VALUE);
1575 }
1576
1577 /* ARGSUSED0 */
1578 static nwam_error_t
valid_link_autopush(nwam_value_t value)1579 valid_link_autopush(nwam_value_t value)
1580 {
1581 return (NWAM_SUCCESS);
1582 }
1583
1584 static nwam_error_t
valid_ip_version(nwam_value_t value)1585 valid_ip_version(nwam_value_t value)
1586 {
1587 uint64_t *versions;
1588 uint_t i, numvalues;
1589
1590 if (nwam_value_get_uint64_array(value, &versions, &numvalues)
1591 != NWAM_SUCCESS)
1592 return (NWAM_ENTITY_INVALID_VALUE);
1593
1594 for (i = 0; i < numvalues; i++) {
1595 if (versions[i] != IPV4_VERSION &&
1596 versions[i] != IPV6_VERSION)
1597 return (NWAM_ENTITY_INVALID_VALUE);
1598 }
1599 return (NWAM_SUCCESS);
1600 }
1601
1602 static nwam_error_t
valid_addrsrc_v4(nwam_value_t value)1603 valid_addrsrc_v4(nwam_value_t value)
1604 {
1605 uint64_t *addrsrc;
1606 uint_t i, numvalues;
1607
1608 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1609 != NWAM_SUCCESS)
1610 return (NWAM_ENTITY_INVALID_VALUE);
1611
1612 for (i = 0; i < numvalues; i++) {
1613 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1614 addrsrc[i] != NWAM_ADDRSRC_STATIC)
1615 return (NWAM_ENTITY_INVALID_VALUE);
1616 }
1617 return (NWAM_SUCCESS);
1618 }
1619
1620 static nwam_error_t
valid_addrsrc_v6(nwam_value_t value)1621 valid_addrsrc_v6(nwam_value_t value)
1622 {
1623 uint64_t *addrsrc;
1624 uint_t i, numvalues;
1625 boolean_t dhcp_found = B_FALSE, autoconf_found = B_FALSE;
1626
1627 if (nwam_value_get_uint64_array(value, &addrsrc, &numvalues)
1628 != NWAM_SUCCESS)
1629 return (NWAM_ENTITY_INVALID_VALUE);
1630
1631 for (i = 0; i < numvalues; i++) {
1632 if (addrsrc[i] != NWAM_ADDRSRC_DHCP &&
1633 addrsrc[i] != NWAM_ADDRSRC_STATIC &&
1634 addrsrc[i] != NWAM_ADDRSRC_AUTOCONF)
1635 return (NWAM_ENTITY_INVALID_VALUE);
1636 if (addrsrc[i] == NWAM_ADDRSRC_DHCP)
1637 dhcp_found = B_TRUE;
1638 if (addrsrc[i] == NWAM_ADDRSRC_AUTOCONF)
1639 autoconf_found = B_TRUE;
1640 }
1641 /*
1642 * DHCP and AUTOCONF need to be specified as v6 address sources
1643 * since there is no way to switch them off in NWAM at present.
1644 */
1645 if (dhcp_found && autoconf_found)
1646 return (NWAM_SUCCESS);
1647 else
1648 return (NWAM_ENTITY_INVALID_VALUE);
1649 }
1650
1651 /* ARGSUSED0 */
1652 static nwam_error_t
valid_link_mtu(nwam_value_t value)1653 valid_link_mtu(nwam_value_t value)
1654 {
1655 return (NWAM_SUCCESS);
1656 }
1657
1658 nwam_error_t
nwam_ncu_validate(nwam_ncu_handle_t ncuh,const char ** errpropp)1659 nwam_ncu_validate(nwam_ncu_handle_t ncuh, const char **errpropp)
1660 {
1661 return (nwam_validate(ncu_prop_table, ncuh, errpropp));
1662 }
1663
1664 /*
1665 * Given the ncu type and ncu class, return the list of properties that needs
1666 * to be set. Note this list is a complete property list that includes both
1667 * the required ones and the optional ones. Caller needs to free prop_list.
1668 */
1669 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)1670 nwam_ncu_get_default_proplist(nwam_ncu_type_t type, nwam_ncu_class_t class,
1671 const char ***prop_list, uint_t *numvalues)
1672 {
1673 uint64_t typeflags = nwam_ncu_type_to_flag(type);
1674 uint64_t classflags = nwam_ncu_class_to_flag(class);
1675
1676 return (nwam_get_default_proplist(ncu_prop_table, typeflags,
1677 classflags, prop_list, numvalues));
1678 }
1679
1680 nwam_error_t
nwam_ncp_get_state(nwam_ncp_handle_t ncph,nwam_state_t * statep,nwam_aux_state_t * auxp)1681 nwam_ncp_get_state(nwam_ncp_handle_t ncph, nwam_state_t *statep,
1682 nwam_aux_state_t *auxp)
1683 {
1684 return (nwam_get_state(ncph->nwh_name, ncph, statep, auxp));
1685 }
1686
1687 nwam_error_t
nwam_ncu_get_state(nwam_ncu_handle_t ncuh,nwam_state_t * statep,nwam_aux_state_t * auxp)1688 nwam_ncu_get_state(nwam_ncu_handle_t ncuh, nwam_state_t *statep,
1689 nwam_aux_state_t *auxp)
1690 {
1691 nwam_ncp_handle_t ncph;
1692 char *ncpname;
1693 nwam_error_t err;
1694
1695 assert(ncuh != NULL);
1696
1697 if ((err = nwam_ncu_get_ncp(ncuh, &ncph)) != NWAM_SUCCESS)
1698 return (err);
1699 if (!nwam_ncp_is_active(ncph)) {
1700 nwam_ncp_free(ncph);
1701 return (NWAM_ENTITY_INVALID);
1702 }
1703 nwam_ncp_free(ncph);
1704
1705 if ((err = nwam_ncu_get_parent_ncp_name(ncuh, &ncpname))
1706 != NWAM_SUCCESS)
1707 return (err);
1708
1709 err = nwam_request_state(NWAM_OBJECT_TYPE_NCU, ncuh->nwh_name, ncpname,
1710 statep, auxp);
1711 free(ncpname);
1712 return (err);
1713 }
1714
1715 nwam_error_t
nwam_ncp_get_active_priority_group(int64_t * priorityp)1716 nwam_ncp_get_active_priority_group(int64_t *priorityp)
1717 {
1718 return (nwam_request_active_priority_group(priorityp));
1719 }
1720