dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libnwam / common / libnwam_util.c
blob0a3185d4a5b2b8bbca465b837eb48e2a24eef843
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <arpa/inet.h>
28 #include <assert.h>
29 #include <atomic.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <inet/ip.h>
33 #include <libintl.h>
34 #include <libproc.h>
35 #include <libscf.h>
36 #include <net/if_dl.h>
37 #include <netinet/in.h>
38 #include <pthread.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <sys/mman.h>
43 #include <sys/socket.h>
44 #include <sys/types.h>
45 #include <unistd.h>
47 #include "libnwam_impl.h"
48 #include <libnwam_priv.h>
49 #include <libnwam.h>
52 * Utility functions for door access, common validation functions etc.
55 pthread_mutex_t door_mutex = PTHREAD_MUTEX_INITIALIZER;
56 int nwam_door_fd = -1;
58 static int
59 open_door(const char *door_name, int *door_fdp)
61 struct door_info dinfo;
62 int err = 0;
64 (void) pthread_mutex_lock(&door_mutex);
66 if (*door_fdp != -1) {
67 /* Check door fd is not old (from previous nwamd). */
68 if (door_info(*door_fdp, &dinfo) != 0 ||
69 (dinfo.di_attributes & DOOR_REVOKED) != 0) {
70 (void) close(*door_fdp);
71 *door_fdp = -1;
74 if (*door_fdp == -1) {
75 *door_fdp = open(door_name, O_RDONLY);
76 if (*door_fdp == -1)
77 err = errno;
80 (void) pthread_mutex_unlock(&door_mutex);
82 return (err);
85 int
86 nwam_make_door_call(const char *door_name, int *door_fdp,
87 void *request, size_t request_size)
89 int err;
90 door_arg_t door_args;
92 door_args.data_ptr = (void *)request;
93 door_args.data_size = request_size;
94 door_args.desc_ptr = NULL;
95 door_args.desc_num = 0;
96 door_args.rbuf = (void *)request;
97 door_args.rsize = request_size;
99 if ((err = open_door(door_name, door_fdp)) != 0)
100 return (err);
102 if (door_call(*door_fdp, &door_args) == -1)
103 return (errno);
105 return (0);
108 static nwam_error_t
109 send_msg_to_nwam(nwamd_door_arg_t *request)
111 int err;
113 if ((err = nwam_make_door_call(NWAM_DOOR, &nwam_door_fd,
114 request, sizeof (nwamd_door_arg_t))) != 0) {
115 if (err == ENOENT)
116 return (NWAM_ERROR_BIND);
117 return (nwam_errno_to_nwam_error(err));
120 switch (request->nwda_status) {
121 case NWAM_REQUEST_STATUS_OK:
122 return (NWAM_SUCCESS);
123 case NWAM_REQUEST_STATUS_UNKNOWN:
124 return (NWAM_INVALID_ARG);
125 case NWAM_REQUEST_STATUS_ALREADY:
126 return (NWAM_ENTITY_IN_USE);
127 case NWAM_REQUEST_STATUS_FAILED:
128 return (request->nwda_error);
129 default:
130 return (NWAM_ERROR_INTERNAL);
134 nwam_error_t
135 nwam_request_register_unregister(nwam_request_type_t type,
136 const char *event_msg_file)
138 nwamd_door_arg_t req;
140 req.nwda_type = type;
142 (void) strlcpy(req.nwda_data.nwdad_register_info.nwdad_name,
143 event_msg_file,
144 sizeof (req.nwda_data.nwdad_register_info.nwdad_name));
146 return (send_msg_to_nwam(&req));
149 nwam_error_t
150 nwam_request_action(nwam_object_type_t object_type,
151 const char *name, const char *parent, nwam_action_t action)
153 nwamd_door_arg_t req;
155 assert(name != NULL);
157 req.nwda_type = NWAM_REQUEST_TYPE_ACTION;
158 req.nwda_data.nwdad_object_action.nwdad_object_type = object_type;
159 req.nwda_data.nwdad_object_action.nwdad_action = action;
160 (void) strlcpy(req.nwda_data.nwdad_object_action.nwdad_name, name,
161 sizeof (req.nwda_data.nwdad_object_action.nwdad_name));
162 if (parent != NULL) {
163 (void) strlcpy(req.nwda_data.nwdad_object_action.nwdad_parent,
164 parent,
165 sizeof (req.nwda_data.nwdad_object_action.nwdad_parent));
166 } else {
167 req.nwda_data.nwdad_object_action.nwdad_parent[0] = '\0';
170 return (send_msg_to_nwam(&req));
173 nwam_error_t
174 nwam_request_state(nwam_object_type_t object_type, const char *name,
175 const char *parent, nwam_state_t *statep, nwam_aux_state_t *auxp)
177 nwamd_door_arg_t req;
178 nwam_error_t err;
180 assert(name != NULL && statep != NULL && auxp != NULL);
182 req.nwda_type = NWAM_REQUEST_TYPE_STATE;
184 req.nwda_data.nwdad_object_state.nwdad_object_type = object_type;
186 (void) strlcpy(req.nwda_data.nwdad_object_state.nwdad_name, name,
187 sizeof (req.nwda_data.nwdad_object_state.nwdad_name));
188 if (parent != NULL) {
189 (void) strlcpy(req.nwda_data.nwdad_object_state.nwdad_parent,
190 parent,
191 sizeof (req.nwda_data.nwdad_object_state.nwdad_parent));
194 err = send_msg_to_nwam(&req);
196 if (err == NWAM_SUCCESS) {
197 *statep = req.nwda_data.nwdad_object_state.nwdad_state;
198 *auxp = req.nwda_data.nwdad_object_state.nwdad_aux_state;
201 return (err);
204 nwam_error_t
205 nwam_request_wlan(nwam_request_type_t type, const char *name,
206 const char *essid, const char *bssid, uint32_t security_mode,
207 uint_t keyslot, const char *key, boolean_t add_to_known_wlans)
209 nwamd_door_arg_t req;
211 assert(name != NULL);
213 req.nwda_type = type;
215 (void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_name, name,
216 sizeof (req.nwda_data.nwdad_wlan_info));
217 if (essid != NULL) {
218 (void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_essid, essid,
219 sizeof (req.nwda_data.nwdad_wlan_info.nwdad_essid));
220 } else {
221 req.nwda_data.nwdad_wlan_info.nwdad_essid[0] = '\0';
223 if (bssid != NULL) {
224 (void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_bssid, bssid,
225 sizeof (req.nwda_data.nwdad_wlan_info.nwdad_bssid));
226 } else {
227 req.nwda_data.nwdad_wlan_info.nwdad_bssid[0] = '\0';
229 if (key != NULL) {
230 (void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_key, key,
231 sizeof (req.nwda_data.nwdad_wlan_info.nwdad_key));
232 req.nwda_data.nwdad_wlan_info.nwdad_keyslot = keyslot;
233 } else {
234 req.nwda_data.nwdad_wlan_info.nwdad_key[0] = '\0';
237 req.nwda_data.nwdad_wlan_info.nwdad_security_mode = security_mode;
238 req.nwda_data.nwdad_wlan_info.nwdad_add_to_known_wlans =
239 add_to_known_wlans;
241 return (send_msg_to_nwam(&req));
244 nwam_error_t
245 nwam_request_wlan_scan_results(const char *name, uint_t *num_wlansp,
246 nwam_wlan_t **wlansp)
248 nwamd_door_arg_t req;
249 nwam_error_t err;
251 assert(name != NULL && num_wlansp != NULL && wlansp != NULL);
253 req.nwda_type = NWAM_REQUEST_TYPE_WLAN_SCAN_RESULTS;
255 (void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_name, name,
256 sizeof (req.nwda_data.nwdad_wlan_info.nwdad_name));
258 if ((err = send_msg_to_nwam(&req)) != NWAM_SUCCESS)
259 return (err);
261 *num_wlansp = req.nwda_data.nwdad_wlan_info.nwdad_num_wlans;
263 *wlansp = calloc(*num_wlansp, sizeof (nwam_wlan_t));
264 if (*wlansp == NULL)
265 return (NWAM_NO_MEMORY);
267 (void) memcpy(*wlansp, req.nwda_data.nwdad_wlan_info.nwdad_wlans,
268 *num_wlansp * sizeof (nwam_wlan_t));
270 return (NWAM_SUCCESS);
273 nwam_error_t
274 nwam_request_active_priority_group(int64_t *priorityp)
276 nwamd_door_arg_t req;
277 nwam_error_t err;
279 assert(priorityp != NULL);
281 req.nwda_type = NWAM_REQUEST_TYPE_PRIORITY_GROUP;
282 err = send_msg_to_nwam(&req);
284 if (err == NWAM_SUCCESS)
285 *priorityp =
286 req.nwda_data.nwdad_priority_group_info.nwdad_priority;
288 return (err);
291 /* String conversion functions */
293 const char *
294 nwam_value_type_to_string(nwam_value_type_t type)
296 switch (type) {
297 case NWAM_VALUE_TYPE_BOOLEAN:
298 return ("boolean");
299 case NWAM_VALUE_TYPE_INT64:
300 return ("int64");
301 case NWAM_VALUE_TYPE_UINT64:
302 return ("uint64");
303 case NWAM_VALUE_TYPE_STRING:
304 return ("string");
305 default:
306 return ("unknown");
310 nwam_value_type_t
311 nwam_string_to_value_type(const char *typestr)
313 if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_BOOLEAN),
314 strlen(typestr)) == 0)
315 return (NWAM_VALUE_TYPE_BOOLEAN);
316 if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_INT64),
317 strlen(typestr)) == 0)
318 return (NWAM_VALUE_TYPE_INT64);
319 if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_UINT64),
320 strlen(typestr)) == 0)
321 return (NWAM_VALUE_TYPE_UINT64);
322 if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_STRING),
323 strlen(typestr)) == 0)
324 return (NWAM_VALUE_TYPE_STRING);
325 return (NWAM_VALUE_TYPE_UNKNOWN);
328 const char *
329 nwam_action_to_string(nwam_action_t action)
331 switch (action) {
332 case NWAM_ACTION_ADD:
333 return ("add");
334 case NWAM_ACTION_REMOVE:
335 return ("remove");
336 case NWAM_ACTION_REFRESH:
337 return ("refresh");
338 case NWAM_ACTION_ENABLE:
339 return ("enable");
340 case NWAM_ACTION_DISABLE:
341 return ("disable");
342 case NWAM_ACTION_DESTROY:
343 return ("destroy");
344 default:
345 return ("unknown");
349 const char *
350 nwam_event_type_to_string(int event_type)
352 switch (event_type) {
353 case NWAM_EVENT_TYPE_NOOP:
354 return ("NOOP");
355 case NWAM_EVENT_TYPE_INIT:
356 return ("INIT");
357 case NWAM_EVENT_TYPE_SHUTDOWN:
358 return ("SHUTDOWN");
359 case NWAM_EVENT_TYPE_OBJECT_ACTION:
360 return ("OBJECT_ACTION");
361 case NWAM_EVENT_TYPE_OBJECT_STATE:
362 return ("OBJECT_STATE");
363 case NWAM_EVENT_TYPE_PRIORITY_GROUP:
364 return ("PRIORITY_GROUP");
365 case NWAM_EVENT_TYPE_INFO:
366 return ("INFO");
367 case NWAM_EVENT_TYPE_WLAN_SCAN_REPORT:
368 return ("WLAN_SCAN_REPORT");
369 case NWAM_EVENT_TYPE_WLAN_NEED_CHOICE:
370 return ("WLAN_NEED_CHOICE");
371 case NWAM_EVENT_TYPE_WLAN_NEED_KEY:
372 return ("WLAN_NEED_KEY");
373 case NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT:
374 return ("WLAN_CONNECTION_REPORT");
375 case NWAM_EVENT_TYPE_IF_ACTION:
376 return ("IF_ACTION");
377 case NWAM_EVENT_TYPE_IF_STATE:
378 return ("IF_STATE");
379 case NWAM_EVENT_TYPE_LINK_ACTION:
380 return ("LINK_ACTION");
381 case NWAM_EVENT_TYPE_LINK_STATE:
382 return ("LINK_STATE");
383 default:
384 return ("UNKNOWN");
388 const char *
389 nwam_state_to_string(nwam_state_t state)
391 switch (state) {
392 case NWAM_STATE_UNINITIALIZED:
393 return ("uninitialized");
394 case NWAM_STATE_INITIALIZED:
395 return ("initialized");
396 case NWAM_STATE_OFFLINE:
397 return ("offline");
398 case NWAM_STATE_OFFLINE_TO_ONLINE:
399 return ("offline*");
400 case NWAM_STATE_ONLINE_TO_OFFLINE:
401 return ("online*");
402 case NWAM_STATE_ONLINE:
403 return ("online");
404 case NWAM_STATE_MAINTENANCE:
405 return ("maintenance");
406 case NWAM_STATE_DEGRADED:
407 return ("degraded");
408 case NWAM_STATE_DISABLED:
409 return ("disabled");
410 default:
411 return ("unknown");
415 const char *
416 nwam_aux_state_to_string(nwam_aux_state_t aux_state)
418 switch (aux_state) {
419 case NWAM_AUX_STATE_UNINITIALIZED:
420 return ("uninitialized");
421 case NWAM_AUX_STATE_INITIALIZED:
422 return ("(re)initialized but not configured");
423 case NWAM_AUX_STATE_CONDITIONS_NOT_MET:
424 return ("conditions for activation are unmet");
425 case NWAM_AUX_STATE_MANUAL_DISABLE:
426 return ("disabled by administrator");
427 case NWAM_AUX_STATE_METHOD_FAILED:
428 return ("method/service failed");
429 case NWAM_AUX_STATE_METHOD_MISSING:
430 return ("method or FMRI not specified");
431 case NWAM_AUX_STATE_INVALID_CONFIG:
432 return ("invalid configuration values");
433 case NWAM_AUX_STATE_METHOD_RUNNING:
434 return ("method/service executing");
435 case NWAM_AUX_STATE_ACTIVE:
436 return ("active");
437 case NWAM_AUX_STATE_LINK_WIFI_SCANNING:
438 return ("scanning for WiFi networks");
439 case NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION:
440 return ("need WiFi network selection");
441 case NWAM_AUX_STATE_LINK_WIFI_NEED_KEY:
442 return ("need WiFi security key");
443 case NWAM_AUX_STATE_LINK_WIFI_CONNECTING:
444 return ("connecting to WiFi network");
445 case NWAM_AUX_STATE_IF_WAITING_FOR_ADDR:
446 return ("waiting for IP address to be set");
447 case NWAM_AUX_STATE_IF_DHCP_TIMED_OUT:
448 return ("DHCP wait timeout, still trying...");
449 case NWAM_AUX_STATE_IF_DUPLICATE_ADDR:
450 return ("duplicate address detected");
451 case NWAM_AUX_STATE_UP:
452 return ("interface/link is up");
453 case NWAM_AUX_STATE_DOWN:
454 return ("interface/link is down");
455 case NWAM_AUX_STATE_NOT_FOUND:
456 return ("interface/link not found");
457 default:
458 return ("unknown");
462 const char *
463 nwam_object_type_to_string(nwam_object_type_t type)
465 switch (type) {
466 case NWAM_OBJECT_TYPE_NCP:
467 return ("ncp");
468 case NWAM_OBJECT_TYPE_NCU:
469 return ("ncu");
470 case NWAM_OBJECT_TYPE_LOC:
471 return ("loc");
472 case NWAM_OBJECT_TYPE_ENM:
473 return ("enm");
474 case NWAM_OBJECT_TYPE_KNOWN_WLAN:
475 return ("known wlan");
476 default:
477 return ("unknown");
481 nwam_object_type_t
482 nwam_string_to_object_type(const char *typestr)
484 if (strcasecmp(typestr,
485 nwam_object_type_to_string(NWAM_OBJECT_TYPE_NCP)) == 0)
486 return (NWAM_OBJECT_TYPE_NCP);
487 if (strcasecmp(typestr,
488 nwam_object_type_to_string(NWAM_OBJECT_TYPE_NCU)) == 0)
489 return (NWAM_OBJECT_TYPE_NCU);
490 if (strcasecmp(typestr,
491 nwam_object_type_to_string(NWAM_OBJECT_TYPE_LOC)) == 0)
492 return (NWAM_OBJECT_TYPE_LOC);
493 if (strcasecmp(typestr,
494 nwam_object_type_to_string(NWAM_OBJECT_TYPE_ENM)) == 0)
495 return (NWAM_OBJECT_TYPE_ENM);
496 if (strcasecmp(typestr,
497 nwam_object_type_to_string(NWAM_OBJECT_TYPE_KNOWN_WLAN)) == 0)
498 return (NWAM_OBJECT_TYPE_KNOWN_WLAN);
499 return (NWAM_OBJECT_TYPE_UNKNOWN);
502 nwam_error_t
503 nwam_errno_to_nwam_error(int errnum)
505 switch (errnum) {
506 case 0:
507 return (NWAM_SUCCESS);
508 case EBADF:
509 return (NWAM_ERROR_BIND);
510 case EPERM:
511 case EACCES:
512 return (NWAM_PERMISSION_DENIED);
513 case ENOENT:
514 return (NWAM_ENTITY_NOT_FOUND);
515 case EIDRM:
516 return (NWAM_ENTITY_INVALID);
517 case EEXIST:
518 return (NWAM_ENTITY_EXISTS);
519 case EAGAIN:
520 case EBUSY:
521 return (NWAM_ENTITY_IN_USE);
522 case ENOMEM:
523 case ENOSPC:
524 return (NWAM_NO_MEMORY);
525 case EINVAL:
526 case E2BIG:
527 return (NWAM_INVALID_ARG);
528 default:
529 return (NWAM_ERROR_INTERNAL);
533 /* Common validation functions */
536 * Do the flags represent a subset of valid_flags?
538 nwam_error_t
539 nwam_valid_flags(uint64_t flags, uint64_t valid_flags)
542 if ((flags | valid_flags) != valid_flags)
543 return (NWAM_INVALID_ARG);
544 return (NWAM_SUCCESS);
547 nwam_error_t
548 nwam_valid_condition(nwam_value_t value)
550 char **conditions;
551 uint_t i, numvalues;
552 nwam_condition_object_type_t object_type;
553 nwam_condition_t condition;
555 if (nwam_value_get_string_array(value, &conditions, &numvalues)
556 != NWAM_SUCCESS)
557 return (NWAM_ENTITY_INVALID_VALUE);
559 for (i = 0; i < numvalues; i++) {
560 char *object_name = NULL;
562 if (nwam_condition_string_to_condition(conditions[i],
563 &object_type, &condition, &object_name) != NWAM_SUCCESS)
564 return (NWAM_ENTITY_INVALID_VALUE);
565 free(object_name);
567 return (NWAM_SUCCESS);
570 /* check if boolean values are correct, generalize for array of booleans */
571 nwam_error_t
572 nwam_valid_boolean(nwam_value_t value)
574 boolean_t *val;
575 uint_t i, numvalues;
577 if (nwam_value_get_boolean_array(value, &val, &numvalues)
578 != NWAM_SUCCESS)
579 return (NWAM_ENTITY_INVALID_VALUE);
581 for (i = 0; i < numvalues; i++) {
582 if (val[i] != B_TRUE && val[i] != B_FALSE)
583 return (NWAM_ENTITY_INVALID_VALUE);
585 return (NWAM_SUCCESS);
588 /* check if uint64 values are correct, generalize for array of ints */
589 nwam_error_t
590 nwam_valid_uint64(nwam_value_t value)
592 int64_t *val;
593 uint_t i, numvalues;
595 if (nwam_value_get_int64_array(value, &val, &numvalues)
596 != NWAM_SUCCESS)
597 return (NWAM_ENTITY_INVALID_VALUE);
599 for (i = 0; i < numvalues; i++) {
600 if (val[i] < 0)
601 return (NWAM_ENTITY_INVALID_VALUE);
603 return (NWAM_SUCCESS);
606 /* check if domain names are correct, generalize for array of domains */
607 nwam_error_t
608 nwam_valid_domain(nwam_value_t value)
610 char **domainvalues, *domain;
611 uint_t i, numvalues;
612 int len, j;
614 if (nwam_value_get_string_array(value, &domainvalues, &numvalues)
615 != NWAM_SUCCESS)
616 return (NWAM_ENTITY_INVALID_VALUE);
618 for (i = 0; i < numvalues; i++) {
620 * First and last character must be alphanumeric.
621 * Only '.' and '-' are allowed.
623 domain = domainvalues[i];
624 len = strlen(domain);
625 if (!isalnum(domain[0]) || !isalnum(domain[len-1]))
626 return (NWAM_ENTITY_INVALID_VALUE);
627 for (j = 0; j < len; j++) {
628 if (!isalnum(domain[j]) &&
629 domain[j] != '.' && domain[j] != '-')
630 return (NWAM_ENTITY_INVALID_VALUE);
633 return (NWAM_SUCCESS);
636 /* check if address prefix is valid */
637 static nwam_error_t
638 nwam_valid_prefix(char *addr, int max_plen)
640 char *prefix, *end;
641 int prefixlen;
643 if ((prefix = strchr(addr, '/')) != NULL) {
644 prefix++;
645 prefixlen = strtol(prefix, &end, 10);
646 if (prefix == end || prefixlen < 0 || prefixlen > max_plen)
647 return (NWAM_ENTITY_INVALID_VALUE);
649 return (NWAM_SUCCESS);
652 /* check if IPv4 addresses are correct, generalize for array of addresses */
653 nwam_error_t
654 nwam_valid_host_v4(nwam_value_t value)
656 char **addrvalues, *addr;
657 uint_t i, numvalues;
658 struct sockaddr_in sa;
660 if (nwam_value_get_string_array(value, &addrvalues, &numvalues)
661 != NWAM_SUCCESS)
662 return (NWAM_ENTITY_INVALID_VALUE);
664 for (i = 0; i < numvalues; i++) {
665 addr = strdup(addrvalues[i]);
666 if (nwam_valid_prefix(addr, IP_ABITS) != NWAM_SUCCESS) {
667 free(addr);
668 return (NWAM_ENTITY_INVALID_VALUE);
670 /* replace '/' with '\0' */
671 addr = strsep(&addr, "/");
672 if (inet_pton(AF_INET, addr, &(sa.sin_addr)) != 1) {
673 free(addr);
674 return (NWAM_ENTITY_INVALID_VALUE);
676 free(addr);
678 return (NWAM_SUCCESS);
681 /* Check if IPv4 address for default route is valid */
682 nwam_error_t
683 nwam_valid_route_v4(nwam_value_t value)
685 char *addrvalue;
686 struct sockaddr_in sa;
688 if (nwam_value_get_string(value, &addrvalue) != NWAM_SUCCESS)
689 return (NWAM_ENTITY_INVALID_VALUE);
691 if (inet_pton(AF_INET, addrvalue, &(sa.sin_addr)) != 1)
692 return (NWAM_ENTITY_INVALID_VALUE);
694 return (NWAM_SUCCESS);
697 /* check if IPv6 addresses are correct, generalize for array of addresses */
698 nwam_error_t
699 nwam_valid_host_v6(nwam_value_t value)
701 char **addrvalues, *addr;
702 uint_t i, numvalues;
703 struct sockaddr_in6 sa;
705 if (nwam_value_get_string_array(value, &addrvalues, &numvalues)
706 != NWAM_SUCCESS)
707 return (NWAM_ENTITY_INVALID_VALUE);
709 for (i = 0; i < numvalues; i++) {
710 addr = strdup(addrvalues[i]);
711 if (nwam_valid_prefix(addr, IPV6_ABITS) != NWAM_SUCCESS) {
712 free(addr);
713 return (NWAM_ENTITY_INVALID_VALUE);
715 /* replace '/' with '\0' */
716 addr = strsep(&addr, "/");
717 if (inet_pton(AF_INET6, addr, &(sa.sin6_addr)) != 1) {
718 free(addr);
719 return (NWAM_ENTITY_INVALID_VALUE);
721 free(addr);
723 return (NWAM_SUCCESS);
726 /* Check if IPv4 address for default route is valid */
727 nwam_error_t
728 nwam_valid_route_v6(nwam_value_t value)
730 char *addrvalue;
731 struct sockaddr_in6 sa;
733 if (nwam_value_get_string(value, &addrvalue) != NWAM_SUCCESS)
734 return (NWAM_ENTITY_INVALID_VALUE);
736 if (inet_pton(AF_INET6, addrvalue, &(sa.sin6_addr)) != 1)
737 return (NWAM_ENTITY_INVALID_VALUE);
739 return (NWAM_SUCCESS);
742 nwam_error_t
743 nwam_valid_host_any(nwam_value_t value)
745 if (nwam_valid_host_v4(value) != NWAM_SUCCESS &&
746 nwam_valid_host_v6(value) != NWAM_SUCCESS)
747 return (NWAM_ENTITY_INVALID_VALUE);
748 return (NWAM_SUCCESS);
751 nwam_error_t
752 nwam_valid_host_or_domain(nwam_value_t value)
754 if (nwam_valid_host_any(value) != NWAM_SUCCESS &&
755 nwam_valid_domain(value) != NWAM_SUCCESS)
756 return (NWAM_ENTITY_INVALID_VALUE);
757 return (NWAM_SUCCESS);
760 /* We do not validate file existence, merely that it is an absolute path. */
761 nwam_error_t
762 nwam_valid_file(nwam_value_t value)
764 char **files;
765 uint_t i, numvalues;
767 if (nwam_value_get_string_array(value, &files, &numvalues)
768 != NWAM_SUCCESS)
769 return (NWAM_ENTITY_INVALID_VALUE);
771 for (i = 0; i < numvalues; i++) {
772 int j = 0;
773 while (isspace(files[i][j]))
774 j++;
775 if (files[i][j] != '/')
776 return (NWAM_ENTITY_INVALID_VALUE);
778 return (NWAM_SUCCESS);
782 * We do not validate existence of the object pointed to by the FMRI
783 * but merely ensure that it is a valid FMRI. We do this by
784 * using scf_handle_decode_fmri(), but ignore all errors bar
785 * SCF_ERROR_INVALID_ARGUMENT (which indicates the FMRI is invalid).
787 nwam_error_t
788 nwam_valid_fmri(nwam_value_t value)
790 char **valstr;
791 scf_handle_t *h = NULL;
792 scf_service_t *svc = NULL;
793 uint_t i, numvalues;
794 nwam_error_t err = NWAM_SUCCESS;
796 if ((err = nwam_value_get_string_array(value, &valstr, &numvalues))
797 != NWAM_SUCCESS)
798 return (err);
800 h = scf_handle_create(SCF_VERSION);
801 if (h == NULL)
802 return (NWAM_ERROR_INTERNAL);
804 if (scf_handle_bind(h) != 0) {
805 err = NWAM_ERROR_INTERNAL;
806 goto out;
809 if ((svc = scf_service_create(h)) == NULL) {
810 err = NWAM_ERROR_INTERNAL;
811 goto out;
815 for (i = 0; i < numvalues; i++) {
816 if (scf_handle_decode_fmri(h, valstr[i], NULL, svc,
817 NULL, NULL, NULL, SCF_DECODE_FMRI_TRUNCATE) == 0 ||
818 scf_error() != SCF_ERROR_INVALID_ARGUMENT) {
819 err = NWAM_SUCCESS;
820 continue;
822 err = NWAM_ENTITY_INVALID_VALUE;
823 break;
825 out:
826 scf_service_destroy(svc);
827 scf_handle_destroy(h);
828 return (err);
831 /* verifies mac-address and bssids */
832 nwam_error_t
833 nwam_valid_mac_addr(nwam_value_t value)
835 char **mac_addrs, *addr;
836 uchar_t *hwaddr;
837 int hwaddrlen, j;
838 uint_t i, numvalues;
840 if (nwam_value_get_string_array(value, &mac_addrs, &numvalues)
841 != NWAM_SUCCESS)
842 return (NWAM_ENTITY_INVALID_VALUE);
844 for (i = 0; i < numvalues; i++) {
845 addr = mac_addrs[i];
846 j = 0;
848 /* validate that a-fA-F0-9 and ':' only */
849 while (addr[j] != 0) {
850 if (!isxdigit(addr[j]) && addr[j] != ':')
851 return (NWAM_ENTITY_INVALID_VALUE);
852 j++;
855 if ((hwaddr = _link_aton(addr, &hwaddrlen)) == NULL)
856 return (NWAM_ENTITY_INVALID_VALUE);
857 free(hwaddr);
860 return (NWAM_SUCCESS);
863 boolean_t
864 nwam_uid_is_special(void)
866 uid_t uid = getuid();
867 return (uid == UID_NETADM || uid == 0);
870 nwam_error_t
871 nwam_get_smf_string_property(const char *fmri, const char *pgname,
872 const char *propname, char **valuep)
874 scf_handle_t *h = NULL;
875 scf_snapshot_t *snap = NULL;
876 scf_instance_t *inst = NULL;
877 scf_propertygroup_t *pg = NULL;
878 scf_property_t *prop = NULL;
879 scf_value_t *val = NULL;
880 nwam_error_t err = NWAM_SUCCESS;
882 if ((*valuep = malloc(NWAM_MAX_NAME_LEN)) == NULL)
883 return (NWAM_NO_MEMORY);
885 if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
886 scf_handle_bind(h) != 0 ||
887 (inst = scf_instance_create(h)) == NULL ||
888 (snap = scf_snapshot_create(h)) == NULL ||
889 (pg = scf_pg_create(h)) == NULL ||
890 (prop = scf_property_create(h)) == NULL ||
891 (val = scf_value_create(h)) == NULL) {
892 err = NWAM_ERROR_INTERNAL;
893 goto out;
895 if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst,
896 NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
897 err = NWAM_ENTITY_NOT_FOUND;
898 goto out;
900 /* Retrieve value from running snapshot (if present) */
901 if (scf_instance_get_snapshot(inst, "running", snap) != 0) {
902 scf_snapshot_destroy(snap);
903 snap = NULL;
905 if (scf_instance_get_pg_composed(inst, snap, pgname, pg) != 0 ||
906 scf_pg_get_property(pg, propname, prop) != 0 ||
907 scf_property_get_value(prop, val) != 0 ||
908 scf_value_get_astring(val, *valuep, NWAM_MAX_NAME_LEN) == -1) {
909 err = NWAM_ENTITY_NOT_FOUND;
911 out:
912 if (err != NWAM_SUCCESS)
913 free(*valuep);
915 scf_value_destroy(val);
916 scf_property_destroy(prop);
917 scf_pg_destroy(pg);
918 if (snap != NULL)
919 scf_snapshot_destroy(snap);
920 scf_instance_destroy(inst);
921 scf_handle_destroy(h);
923 return (err);
926 nwam_error_t
927 nwam_set_smf_string_property(const char *fmri, const char *pgname,
928 const char *propname, const char *propval)
930 scf_handle_t *h = NULL;
931 scf_instance_t *inst = NULL;
932 scf_propertygroup_t *pg = NULL;
933 scf_property_t *prop = NULL;
934 scf_value_t *val = NULL;
935 scf_transaction_t *tx = NULL;
936 scf_transaction_entry_t *ent = NULL;
937 nwam_error_t err = NWAM_SUCCESS;
938 int result;
940 if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
941 scf_handle_bind(h) != 0 ||
942 (inst = scf_instance_create(h)) == NULL ||
943 (pg = scf_pg_create(h)) == NULL ||
944 (prop = scf_property_create(h)) == NULL ||
945 (val = scf_value_create(h)) == NULL ||
946 scf_value_set_astring(val, propval) != 0 ||
947 (tx = scf_transaction_create(h)) == NULL ||
948 (ent = scf_entry_create(h)) == NULL) {
949 err = NWAM_ERROR_INTERNAL;
950 goto out;
952 if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst,
953 NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0 ||
954 scf_instance_get_pg_composed(inst, NULL, pgname, pg) != 0) {
955 err = NWAM_ENTITY_NOT_FOUND;
956 goto out;
959 retry:
960 if (scf_transaction_start(tx, pg) == -1 ||
961 scf_transaction_property_change(tx, ent, propname, SCF_TYPE_ASTRING)
962 == -1 || scf_entry_add_value(ent, val) != 0) {
963 err = NWAM_ERROR_INTERNAL;
964 goto out;
967 result = scf_transaction_commit(tx);
968 switch (result) {
969 case 1:
970 (void) smf_refresh_instance(fmri);
971 break;
972 case 0:
973 scf_transaction_reset(tx);
974 if (scf_pg_update(pg) == -1) {
975 err = NWAM_ERROR_INTERNAL;
976 goto out;
978 goto retry;
979 default:
980 err = NWAM_ERROR_INTERNAL;
981 break;
983 out:
984 scf_value_destroy(val);
985 scf_property_destroy(prop);
986 scf_pg_destroy(pg);
987 scf_instance_destroy(inst);
988 scf_handle_destroy(h);
990 return (err);