xref: /titanic_52/usr/src/lib/libnwam/common/libnwam_util.c (revision 69b43529e65fb6eb0c88e6b7b42025e9bf025b8a)
16ba597c5SAnurag S. Maskey /*
26ba597c5SAnurag S. Maskey  * CDDL HEADER START
36ba597c5SAnurag S. Maskey  *
46ba597c5SAnurag S. Maskey  * The contents of this file are subject to the terms of the
56ba597c5SAnurag S. Maskey  * Common Development and Distribution License (the "License").
66ba597c5SAnurag S. Maskey  * You may not use this file except in compliance with the License.
76ba597c5SAnurag S. Maskey  *
86ba597c5SAnurag S. Maskey  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96ba597c5SAnurag S. Maskey  * or http://www.opensolaris.org/os/licensing.
106ba597c5SAnurag S. Maskey  * See the License for the specific language governing permissions
116ba597c5SAnurag S. Maskey  * and limitations under the License.
126ba597c5SAnurag S. Maskey  *
136ba597c5SAnurag S. Maskey  * When distributing Covered Code, include this CDDL HEADER in each
146ba597c5SAnurag S. Maskey  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156ba597c5SAnurag S. Maskey  * If applicable, add the following below this CDDL HEADER, with the
166ba597c5SAnurag S. Maskey  * fields enclosed by brackets "[]" replaced with your own identifying
176ba597c5SAnurag S. Maskey  * information: Portions Copyright [yyyy] [name of copyright owner]
186ba597c5SAnurag S. Maskey  *
196ba597c5SAnurag S. Maskey  * CDDL HEADER END
206ba597c5SAnurag S. Maskey  */
216ba597c5SAnurag S. Maskey 
226ba597c5SAnurag S. Maskey /*
236ba597c5SAnurag S. Maskey  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
246ba597c5SAnurag S. Maskey  * Use is subject to license terms.
256ba597c5SAnurag S. Maskey  */
266ba597c5SAnurag S. Maskey 
276ba597c5SAnurag S. Maskey #include <arpa/inet.h>
286ba597c5SAnurag S. Maskey #include <assert.h>
296ba597c5SAnurag S. Maskey #include <atomic.h>
306ba597c5SAnurag S. Maskey #include <ctype.h>
316ba597c5SAnurag S. Maskey #include <errno.h>
326ba597c5SAnurag S. Maskey #include <inet/ip.h>
336ba597c5SAnurag S. Maskey #include <libintl.h>
346ba597c5SAnurag S. Maskey #include <libproc.h>
356ba597c5SAnurag S. Maskey #include <libscf.h>
366ba597c5SAnurag S. Maskey #include <net/if_dl.h>
376ba597c5SAnurag S. Maskey #include <netinet/in.h>
386ba597c5SAnurag S. Maskey #include <pthread.h>
396ba597c5SAnurag S. Maskey #include <stdio.h>
406ba597c5SAnurag S. Maskey #include <stdlib.h>
416ba597c5SAnurag S. Maskey #include <strings.h>
426ba597c5SAnurag S. Maskey #include <sys/mman.h>
436ba597c5SAnurag S. Maskey #include <sys/socket.h>
446ba597c5SAnurag S. Maskey #include <sys/types.h>
456ba597c5SAnurag S. Maskey #include <unistd.h>
466ba597c5SAnurag S. Maskey 
476ba597c5SAnurag S. Maskey #include "libnwam_impl.h"
486ba597c5SAnurag S. Maskey #include <libnwam_priv.h>
496ba597c5SAnurag S. Maskey #include <libnwam.h>
506ba597c5SAnurag S. Maskey 
516ba597c5SAnurag S. Maskey /*
526ba597c5SAnurag S. Maskey  * Utility functions for door access, common validation functions etc.
536ba597c5SAnurag S. Maskey  */
546ba597c5SAnurag S. Maskey 
556ba597c5SAnurag S. Maskey pthread_mutex_t door_mutex = PTHREAD_MUTEX_INITIALIZER;
566ba597c5SAnurag S. Maskey int nwam_door_fd = -1;
576ba597c5SAnurag S. Maskey 
586ba597c5SAnurag S. Maskey static int
596ba597c5SAnurag S. Maskey open_door(const char *door_name, int *door_fdp)
606ba597c5SAnurag S. Maskey {
616ba597c5SAnurag S. Maskey 	struct door_info dinfo;
626ba597c5SAnurag S. Maskey 	int err = 0;
636ba597c5SAnurag S. Maskey 
646ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&door_mutex);
656ba597c5SAnurag S. Maskey 
666ba597c5SAnurag S. Maskey 	if (*door_fdp != -1) {
676ba597c5SAnurag S. Maskey 		/* Check door fd is not old (from previous nwamd). */
686ba597c5SAnurag S. Maskey 		if (door_info(*door_fdp, &dinfo) != 0 ||
696ba597c5SAnurag S. Maskey 		    (dinfo.di_attributes & DOOR_REVOKED) != 0) {
706ba597c5SAnurag S. Maskey 			(void) close(*door_fdp);
716ba597c5SAnurag S. Maskey 			*door_fdp = -1;
726ba597c5SAnurag S. Maskey 		}
736ba597c5SAnurag S. Maskey 	}
746ba597c5SAnurag S. Maskey 	if (*door_fdp == -1) {
756ba597c5SAnurag S. Maskey 		*door_fdp = open(door_name, 0);
766ba597c5SAnurag S. Maskey 		if (*door_fdp == -1)
776ba597c5SAnurag S. Maskey 			err = errno;
786ba597c5SAnurag S. Maskey 	}
796ba597c5SAnurag S. Maskey 
806ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&door_mutex);
816ba597c5SAnurag S. Maskey 
826ba597c5SAnurag S. Maskey 	return (err);
836ba597c5SAnurag S. Maskey }
846ba597c5SAnurag S. Maskey 
856ba597c5SAnurag S. Maskey int
866ba597c5SAnurag S. Maskey nwam_make_door_call(const char *door_name, int *door_fdp,
876ba597c5SAnurag S. Maskey     void *request, size_t request_size)
886ba597c5SAnurag S. Maskey {
896ba597c5SAnurag S. Maskey 	int err;
906ba597c5SAnurag S. Maskey 	door_arg_t door_args;
916ba597c5SAnurag S. Maskey 
926ba597c5SAnurag S. Maskey 	door_args.data_ptr = (void *)request;
936ba597c5SAnurag S. Maskey 	door_args.data_size = request_size;
946ba597c5SAnurag S. Maskey 	door_args.desc_ptr = NULL;
956ba597c5SAnurag S. Maskey 	door_args.desc_num = 0;
966ba597c5SAnurag S. Maskey 	door_args.rbuf = (void *)request;
976ba597c5SAnurag S. Maskey 	door_args.rsize = request_size;
986ba597c5SAnurag S. Maskey 
996ba597c5SAnurag S. Maskey 	if ((err = open_door(door_name, door_fdp)) != 0)
1006ba597c5SAnurag S. Maskey 		return (err);
1016ba597c5SAnurag S. Maskey 
1026ba597c5SAnurag S. Maskey 	if (door_call(*door_fdp, &door_args) == -1)
1036ba597c5SAnurag S. Maskey 		return (errno);
1046ba597c5SAnurag S. Maskey 
1056ba597c5SAnurag S. Maskey 	return (0);
1066ba597c5SAnurag S. Maskey }
1076ba597c5SAnurag S. Maskey 
1086ba597c5SAnurag S. Maskey static nwam_error_t
1096ba597c5SAnurag S. Maskey send_msg_to_nwam(nwamd_door_arg_t *request)
1106ba597c5SAnurag S. Maskey {
1116ba597c5SAnurag S. Maskey 	int err;
1126ba597c5SAnurag S. Maskey 
1136ba597c5SAnurag S. Maskey 	if ((err = nwam_make_door_call(NWAM_DOOR, &nwam_door_fd,
1146ba597c5SAnurag S. Maskey 	    request, sizeof (nwamd_door_arg_t))) != 0) {
1156ba597c5SAnurag S. Maskey 		if (err == ENOENT)
1166ba597c5SAnurag S. Maskey 			return (NWAM_ERROR_BIND);
1176ba597c5SAnurag S. Maskey 		return (nwam_errno_to_nwam_error(err));
1186ba597c5SAnurag S. Maskey 	}
1196ba597c5SAnurag S. Maskey 
1206ba597c5SAnurag S. Maskey 	switch (request->nwda_status) {
1216ba597c5SAnurag S. Maskey 	case NWAM_REQUEST_STATUS_OK:
1226ba597c5SAnurag S. Maskey 		return (NWAM_SUCCESS);
1236ba597c5SAnurag S. Maskey 	case NWAM_REQUEST_STATUS_UNKNOWN:
1246ba597c5SAnurag S. Maskey 		return (NWAM_INVALID_ARG);
1256ba597c5SAnurag S. Maskey 	case NWAM_REQUEST_STATUS_ALREADY:
1266ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_IN_USE);
1276ba597c5SAnurag S. Maskey 	case NWAM_REQUEST_STATUS_FAILED:
1286ba597c5SAnurag S. Maskey 		return (request->nwda_error);
1296ba597c5SAnurag S. Maskey 	default:
1306ba597c5SAnurag S. Maskey 		return (NWAM_ERROR_INTERNAL);
1316ba597c5SAnurag S. Maskey 	}
1326ba597c5SAnurag S. Maskey }
1336ba597c5SAnurag S. Maskey 
1346ba597c5SAnurag S. Maskey nwam_error_t
1356ba597c5SAnurag S. Maskey nwam_request_register_unregister(nwam_request_type_t type,
1366ba597c5SAnurag S. Maskey     const char *event_msg_file)
1376ba597c5SAnurag S. Maskey {
1386ba597c5SAnurag S. Maskey 	nwamd_door_arg_t req;
1396ba597c5SAnurag S. Maskey 
1406ba597c5SAnurag S. Maskey 	req.nwda_type = type;
1416ba597c5SAnurag S. Maskey 
1426ba597c5SAnurag S. Maskey 	(void) strlcpy(req.nwda_data.nwdad_register_info.nwdad_name,
1436ba597c5SAnurag S. Maskey 	    event_msg_file,
1446ba597c5SAnurag S. Maskey 	    sizeof (req.nwda_data.nwdad_register_info.nwdad_name));
1456ba597c5SAnurag S. Maskey 
1466ba597c5SAnurag S. Maskey 	return (send_msg_to_nwam(&req));
1476ba597c5SAnurag S. Maskey }
1486ba597c5SAnurag S. Maskey 
1496ba597c5SAnurag S. Maskey nwam_error_t
1506ba597c5SAnurag S. Maskey nwam_request_action(nwam_object_type_t object_type,
1516ba597c5SAnurag S. Maskey     const char *name, const char *parent, nwam_action_t action)
1526ba597c5SAnurag S. Maskey {
1536ba597c5SAnurag S. Maskey 	nwamd_door_arg_t req;
1546ba597c5SAnurag S. Maskey 
1556ba597c5SAnurag S. Maskey 	assert(name != NULL);
1566ba597c5SAnurag S. Maskey 
1576ba597c5SAnurag S. Maskey 	req.nwda_type = NWAM_REQUEST_TYPE_ACTION;
1586ba597c5SAnurag S. Maskey 	req.nwda_data.nwdad_object_action.nwdad_object_type = object_type;
1596ba597c5SAnurag S. Maskey 	req.nwda_data.nwdad_object_action.nwdad_action = action;
1606ba597c5SAnurag S. Maskey 	(void) strlcpy(req.nwda_data.nwdad_object_action.nwdad_name, name,
1616ba597c5SAnurag S. Maskey 	    sizeof (req.nwda_data.nwdad_object_action.nwdad_name));
1626ba597c5SAnurag S. Maskey 	if (parent != NULL) {
1636ba597c5SAnurag S. Maskey 		(void) strlcpy(req.nwda_data.nwdad_object_action.nwdad_parent,
1646ba597c5SAnurag S. Maskey 		    parent,
1656ba597c5SAnurag S. Maskey 		    sizeof (req.nwda_data.nwdad_object_action.nwdad_parent));
1666ba597c5SAnurag S. Maskey 	} else {
1676ba597c5SAnurag S. Maskey 		req.nwda_data.nwdad_object_action.nwdad_parent[0] = '\0';
1686ba597c5SAnurag S. Maskey 	}
1696ba597c5SAnurag S. Maskey 
1706ba597c5SAnurag S. Maskey 	return (send_msg_to_nwam(&req));
1716ba597c5SAnurag S. Maskey }
1726ba597c5SAnurag S. Maskey 
1736ba597c5SAnurag S. Maskey nwam_error_t
1746ba597c5SAnurag S. Maskey nwam_request_state(nwam_object_type_t object_type, const char *name,
1756ba597c5SAnurag S. Maskey     const char *parent, nwam_state_t *statep, nwam_aux_state_t *auxp)
1766ba597c5SAnurag S. Maskey {
1776ba597c5SAnurag S. Maskey 	nwamd_door_arg_t req;
1786ba597c5SAnurag S. Maskey 	nwam_error_t err;
1796ba597c5SAnurag S. Maskey 
1806ba597c5SAnurag S. Maskey 	assert(name != NULL && statep != NULL && auxp != NULL);
1816ba597c5SAnurag S. Maskey 
1826ba597c5SAnurag S. Maskey 	req.nwda_type = NWAM_REQUEST_TYPE_STATE;
1836ba597c5SAnurag S. Maskey 
1846ba597c5SAnurag S. Maskey 	req.nwda_data.nwdad_object_state.nwdad_object_type = object_type;
1856ba597c5SAnurag S. Maskey 
1866ba597c5SAnurag S. Maskey 	(void) strlcpy(req.nwda_data.nwdad_object_state.nwdad_name, name,
1876ba597c5SAnurag S. Maskey 	    sizeof (req.nwda_data.nwdad_object_state.nwdad_name));
1886ba597c5SAnurag S. Maskey 	if (parent != NULL) {
1896ba597c5SAnurag S. Maskey 		(void) strlcpy(req.nwda_data.nwdad_object_state.nwdad_parent,
1906ba597c5SAnurag S. Maskey 		    parent,
1916ba597c5SAnurag S. Maskey 		    sizeof (req.nwda_data.nwdad_object_state.nwdad_parent));
1926ba597c5SAnurag S. Maskey 	}
1936ba597c5SAnurag S. Maskey 
1946ba597c5SAnurag S. Maskey 	err = send_msg_to_nwam(&req);
1956ba597c5SAnurag S. Maskey 
1966ba597c5SAnurag S. Maskey 	if (err == NWAM_SUCCESS) {
1976ba597c5SAnurag S. Maskey 		*statep = req.nwda_data.nwdad_object_state.nwdad_state;
1986ba597c5SAnurag S. Maskey 		*auxp = req.nwda_data.nwdad_object_state.nwdad_aux_state;
1996ba597c5SAnurag S. Maskey 	}
2006ba597c5SAnurag S. Maskey 
2016ba597c5SAnurag S. Maskey 	return (err);
2026ba597c5SAnurag S. Maskey }
2036ba597c5SAnurag S. Maskey 
2046ba597c5SAnurag S. Maskey nwam_error_t
2056ba597c5SAnurag S. Maskey nwam_request_wlan(nwam_request_type_t type, const char *name,
2066ba597c5SAnurag S. Maskey     const char *essid, const char *bssid, uint32_t security_mode,
2076ba597c5SAnurag S. Maskey     uint_t keyslot, const char *key, boolean_t add_to_known_wlans)
2086ba597c5SAnurag S. Maskey {
2096ba597c5SAnurag S. Maskey 	nwamd_door_arg_t req;
2106ba597c5SAnurag S. Maskey 
2116ba597c5SAnurag S. Maskey 	assert(name != NULL);
2126ba597c5SAnurag S. Maskey 
2136ba597c5SAnurag S. Maskey 	req.nwda_type = type;
2146ba597c5SAnurag S. Maskey 
2156ba597c5SAnurag S. Maskey 	(void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_name, name,
2166ba597c5SAnurag S. Maskey 	    sizeof (req.nwda_data.nwdad_wlan_info));
2176ba597c5SAnurag S. Maskey 	if (essid != NULL) {
2186ba597c5SAnurag S. Maskey 		(void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_essid, essid,
2196ba597c5SAnurag S. Maskey 		    sizeof (req.nwda_data.nwdad_wlan_info.nwdad_essid));
2206ba597c5SAnurag S. Maskey 	} else {
2216ba597c5SAnurag S. Maskey 		req.nwda_data.nwdad_wlan_info.nwdad_essid[0] = '\0';
2226ba597c5SAnurag S. Maskey 	}
2236ba597c5SAnurag S. Maskey 	if (bssid != NULL) {
2246ba597c5SAnurag S. Maskey 		(void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_bssid, bssid,
2256ba597c5SAnurag S. Maskey 		    sizeof (req.nwda_data.nwdad_wlan_info.nwdad_bssid));
2266ba597c5SAnurag S. Maskey 	} else {
2276ba597c5SAnurag S. Maskey 		req.nwda_data.nwdad_wlan_info.nwdad_bssid[0] = '\0';
2286ba597c5SAnurag S. Maskey 	}
2296ba597c5SAnurag S. Maskey 	if (key != NULL) {
2306ba597c5SAnurag S. Maskey 		(void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_key, key,
2316ba597c5SAnurag S. Maskey 		    sizeof (req.nwda_data.nwdad_wlan_info.nwdad_key));
2326ba597c5SAnurag S. Maskey 		req.nwda_data.nwdad_wlan_info.nwdad_keyslot = keyslot;
2336ba597c5SAnurag S. Maskey 	} else {
2346ba597c5SAnurag S. Maskey 		req.nwda_data.nwdad_wlan_info.nwdad_key[0] = '\0';
2356ba597c5SAnurag S. Maskey 	}
2366ba597c5SAnurag S. Maskey 
2376ba597c5SAnurag S. Maskey 	req.nwda_data.nwdad_wlan_info.nwdad_security_mode = security_mode;
2386ba597c5SAnurag S. Maskey 	req.nwda_data.nwdad_wlan_info.nwdad_add_to_known_wlans =
2396ba597c5SAnurag S. Maskey 	    add_to_known_wlans;
2406ba597c5SAnurag S. Maskey 
2416ba597c5SAnurag S. Maskey 	return (send_msg_to_nwam(&req));
2426ba597c5SAnurag S. Maskey }
2436ba597c5SAnurag S. Maskey 
2446ba597c5SAnurag S. Maskey nwam_error_t
2456ba597c5SAnurag S. Maskey nwam_request_wlan_scan_results(const char *name, uint_t *num_wlansp,
2466ba597c5SAnurag S. Maskey     nwam_wlan_t **wlansp)
2476ba597c5SAnurag S. Maskey {
2486ba597c5SAnurag S. Maskey 	nwamd_door_arg_t req;
2496ba597c5SAnurag S. Maskey 	nwam_error_t err;
2506ba597c5SAnurag S. Maskey 
2516ba597c5SAnurag S. Maskey 	assert(name != NULL && num_wlansp != NULL && wlansp != NULL);
2526ba597c5SAnurag S. Maskey 
2536ba597c5SAnurag S. Maskey 	req.nwda_type = NWAM_REQUEST_TYPE_WLAN_SCAN_RESULTS;
2546ba597c5SAnurag S. Maskey 
2556ba597c5SAnurag S. Maskey 	(void) strlcpy(req.nwda_data.nwdad_wlan_info.nwdad_name, name,
2566ba597c5SAnurag S. Maskey 	    sizeof (req.nwda_data.nwdad_wlan_info.nwdad_name));
2576ba597c5SAnurag S. Maskey 
2586ba597c5SAnurag S. Maskey 	if ((err = send_msg_to_nwam(&req)) != NWAM_SUCCESS)
2596ba597c5SAnurag S. Maskey 		return (err);
2606ba597c5SAnurag S. Maskey 
2616ba597c5SAnurag S. Maskey 	*num_wlansp = req.nwda_data.nwdad_wlan_info.nwdad_num_wlans;
2626ba597c5SAnurag S. Maskey 
2636ba597c5SAnurag S. Maskey 	*wlansp = calloc(*num_wlansp, sizeof (nwam_wlan_t));
2646ba597c5SAnurag S. Maskey 	if (*wlansp == NULL)
2656ba597c5SAnurag S. Maskey 		return (NWAM_NO_MEMORY);
2666ba597c5SAnurag S. Maskey 
2676ba597c5SAnurag S. Maskey 	(void) memcpy(*wlansp, req.nwda_data.nwdad_wlan_info.nwdad_wlans,
2686ba597c5SAnurag S. Maskey 	    *num_wlansp * sizeof (nwam_wlan_t));
2696ba597c5SAnurag S. Maskey 
2706ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
2716ba597c5SAnurag S. Maskey }
2726ba597c5SAnurag S. Maskey 
2736ba597c5SAnurag S. Maskey nwam_error_t
2746ba597c5SAnurag S. Maskey nwam_request_active_priority_group(int64_t *priorityp)
2756ba597c5SAnurag S. Maskey {
2766ba597c5SAnurag S. Maskey 	nwamd_door_arg_t req;
2776ba597c5SAnurag S. Maskey 	nwam_error_t err;
2786ba597c5SAnurag S. Maskey 
2796ba597c5SAnurag S. Maskey 	assert(priorityp != NULL);
2806ba597c5SAnurag S. Maskey 
2816ba597c5SAnurag S. Maskey 	req.nwda_type = NWAM_REQUEST_TYPE_PRIORITY_GROUP;
2826ba597c5SAnurag S. Maskey 	err = send_msg_to_nwam(&req);
2836ba597c5SAnurag S. Maskey 
2846ba597c5SAnurag S. Maskey 	if (err == NWAM_SUCCESS)
2856ba597c5SAnurag S. Maskey 		*priorityp =
2866ba597c5SAnurag S. Maskey 		    req.nwda_data.nwdad_priority_group_info.nwdad_priority;
2876ba597c5SAnurag S. Maskey 
2886ba597c5SAnurag S. Maskey 	return (err);
2896ba597c5SAnurag S. Maskey }
2906ba597c5SAnurag S. Maskey 
2916ba597c5SAnurag S. Maskey /* String conversion functions */
2926ba597c5SAnurag S. Maskey 
2936ba597c5SAnurag S. Maskey const char *
2946ba597c5SAnurag S. Maskey nwam_value_type_to_string(nwam_value_type_t type)
2956ba597c5SAnurag S. Maskey {
2966ba597c5SAnurag S. Maskey 	switch (type) {
2976ba597c5SAnurag S. Maskey 	case NWAM_VALUE_TYPE_BOOLEAN:
2986ba597c5SAnurag S. Maskey 		return ("boolean");
2996ba597c5SAnurag S. Maskey 	case NWAM_VALUE_TYPE_INT64:
3006ba597c5SAnurag S. Maskey 		return ("int64");
3016ba597c5SAnurag S. Maskey 	case NWAM_VALUE_TYPE_UINT64:
3026ba597c5SAnurag S. Maskey 		return ("uint64");
3036ba597c5SAnurag S. Maskey 	case NWAM_VALUE_TYPE_STRING:
3046ba597c5SAnurag S. Maskey 		return ("string");
3056ba597c5SAnurag S. Maskey 	default:
3066ba597c5SAnurag S. Maskey 		return ("unknown");
3076ba597c5SAnurag S. Maskey 	}
3086ba597c5SAnurag S. Maskey }
3096ba597c5SAnurag S. Maskey 
3106ba597c5SAnurag S. Maskey nwam_value_type_t
3116ba597c5SAnurag S. Maskey nwam_string_to_value_type(const char *typestr)
3126ba597c5SAnurag S. Maskey {
3136ba597c5SAnurag S. Maskey 	if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_BOOLEAN),
3146ba597c5SAnurag S. Maskey 	    strlen(typestr)) == 0)
3156ba597c5SAnurag S. Maskey 		return (NWAM_VALUE_TYPE_BOOLEAN);
3166ba597c5SAnurag S. Maskey 	if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_INT64),
3176ba597c5SAnurag S. Maskey 	    strlen(typestr)) == 0)
3186ba597c5SAnurag S. Maskey 		return (NWAM_VALUE_TYPE_INT64);
3196ba597c5SAnurag S. Maskey 	if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_UINT64),
3206ba597c5SAnurag S. Maskey 	    strlen(typestr)) == 0)
3216ba597c5SAnurag S. Maskey 		return (NWAM_VALUE_TYPE_UINT64);
3226ba597c5SAnurag S. Maskey 	if (strncmp(typestr, nwam_value_type_to_string(NWAM_VALUE_TYPE_STRING),
3236ba597c5SAnurag S. Maskey 	    strlen(typestr)) == 0)
3246ba597c5SAnurag S. Maskey 		return (NWAM_VALUE_TYPE_STRING);
3256ba597c5SAnurag S. Maskey 	return (NWAM_VALUE_TYPE_UNKNOWN);
3266ba597c5SAnurag S. Maskey }
3276ba597c5SAnurag S. Maskey 
3286ba597c5SAnurag S. Maskey const char *
3296ba597c5SAnurag S. Maskey nwam_action_to_string(nwam_action_t action)
3306ba597c5SAnurag S. Maskey {
3316ba597c5SAnurag S. Maskey 	switch (action) {
3326ba597c5SAnurag S. Maskey 	case NWAM_ACTION_ADD:
3336ba597c5SAnurag S. Maskey 		return ("add");
3346ba597c5SAnurag S. Maskey 	case NWAM_ACTION_REMOVE:
3356ba597c5SAnurag S. Maskey 		return ("remove");
3366ba597c5SAnurag S. Maskey 	case NWAM_ACTION_REFRESH:
3376ba597c5SAnurag S. Maskey 		return ("refresh");
3386ba597c5SAnurag S. Maskey 	case NWAM_ACTION_ENABLE:
3396ba597c5SAnurag S. Maskey 		return ("enable");
3406ba597c5SAnurag S. Maskey 	case NWAM_ACTION_DISABLE:
3416ba597c5SAnurag S. Maskey 		return ("disable");
3426ba597c5SAnurag S. Maskey 	case NWAM_ACTION_DESTROY:
3436ba597c5SAnurag S. Maskey 		return ("destroy");
3446ba597c5SAnurag S. Maskey 	default:
3456ba597c5SAnurag S. Maskey 		return ("unknown");
3466ba597c5SAnurag S. Maskey 	}
3476ba597c5SAnurag S. Maskey }
3486ba597c5SAnurag S. Maskey 
3496ba597c5SAnurag S. Maskey const char *
3506ba597c5SAnurag S. Maskey nwam_event_type_to_string(int event_type)
3516ba597c5SAnurag S. Maskey {
3526ba597c5SAnurag S. Maskey 	switch (event_type) {
3536ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_NOOP:
3546ba597c5SAnurag S. Maskey 		return ("NOOP");
3556ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_INIT:
3566ba597c5SAnurag S. Maskey 		return ("INIT");
3576ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_SHUTDOWN:
3586ba597c5SAnurag S. Maskey 		return ("SHUTDOWN");
3596ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_OBJECT_ACTION:
3606ba597c5SAnurag S. Maskey 		return ("OBJECT_ACTION");
3616ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_OBJECT_STATE:
3626ba597c5SAnurag S. Maskey 		return ("OBJECT_STATE");
3636ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_PRIORITY_GROUP:
3646ba597c5SAnurag S. Maskey 		return ("PRIORITY_GROUP");
3656ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_INFO:
3666ba597c5SAnurag S. Maskey 		return ("INFO");
3676ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_SCAN_REPORT:
3686ba597c5SAnurag S. Maskey 		return ("WLAN_SCAN_REPORT");
3696ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_NEED_CHOICE:
3706ba597c5SAnurag S. Maskey 		return ("WLAN_NEED_CHOICE");
3716ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_NEED_KEY:
3726ba597c5SAnurag S. Maskey 		return ("WLAN_NEED_KEY");
3736ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT:
3746ba597c5SAnurag S. Maskey 		return ("WLAN_CONNECTION_REPORT");
3756ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_IF_ACTION:
3766ba597c5SAnurag S. Maskey 		return ("IF_ACTION");
3776ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_IF_STATE:
3786ba597c5SAnurag S. Maskey 		return ("IF_STATE");
3796ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_LINK_ACTION:
3806ba597c5SAnurag S. Maskey 		return ("LINK_ACTION");
3816ba597c5SAnurag S. Maskey 	case NWAM_EVENT_TYPE_LINK_STATE:
3826ba597c5SAnurag S. Maskey 		return ("LINK_STATE");
3836ba597c5SAnurag S. Maskey 	default:
3846ba597c5SAnurag S. Maskey 		return ("UNKNOWN");
3856ba597c5SAnurag S. Maskey 	}
3866ba597c5SAnurag S. Maskey }
3876ba597c5SAnurag S. Maskey 
3886ba597c5SAnurag S. Maskey const char *
3896ba597c5SAnurag S. Maskey nwam_state_to_string(nwam_state_t state)
3906ba597c5SAnurag S. Maskey {
3916ba597c5SAnurag S. Maskey 	switch (state) {
3926ba597c5SAnurag S. Maskey 	case NWAM_STATE_UNINITIALIZED:
3936ba597c5SAnurag S. Maskey 		return ("uninitialized");
3946ba597c5SAnurag S. Maskey 	case NWAM_STATE_INITIALIZED:
3956ba597c5SAnurag S. Maskey 		return ("initialized");
3966ba597c5SAnurag S. Maskey 	case NWAM_STATE_OFFLINE:
3976ba597c5SAnurag S. Maskey 		return ("offline");
3986ba597c5SAnurag S. Maskey 	case NWAM_STATE_OFFLINE_TO_ONLINE:
3996ba597c5SAnurag S. Maskey 		return ("offline*");
4006ba597c5SAnurag S. Maskey 	case NWAM_STATE_ONLINE_TO_OFFLINE:
4016ba597c5SAnurag S. Maskey 		return ("online*");
4026ba597c5SAnurag S. Maskey 	case NWAM_STATE_ONLINE:
4036ba597c5SAnurag S. Maskey 		return ("online");
4046ba597c5SAnurag S. Maskey 	case NWAM_STATE_MAINTENANCE:
4056ba597c5SAnurag S. Maskey 		return ("maintenance");
4066ba597c5SAnurag S. Maskey 	case NWAM_STATE_DEGRADED:
4076ba597c5SAnurag S. Maskey 		return ("degraded");
4086ba597c5SAnurag S. Maskey 	case NWAM_STATE_DISABLED:
4096ba597c5SAnurag S. Maskey 		return ("disabled");
4106ba597c5SAnurag S. Maskey 	default:
4116ba597c5SAnurag S. Maskey 		return ("unknown");
4126ba597c5SAnurag S. Maskey 	}
4136ba597c5SAnurag S. Maskey }
4146ba597c5SAnurag S. Maskey 
4156ba597c5SAnurag S. Maskey const char *
4166ba597c5SAnurag S. Maskey nwam_aux_state_to_string(nwam_aux_state_t aux_state)
4176ba597c5SAnurag S. Maskey {
4186ba597c5SAnurag S. Maskey 	switch (aux_state) {
4196ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_UNINITIALIZED:
4206ba597c5SAnurag S. Maskey 		return ("uninitialized");
4216ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_INITIALIZED:
4226ba597c5SAnurag S. Maskey 		return ("(re)initialized but not configured");
4236ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_CONDITIONS_NOT_MET:
4246ba597c5SAnurag S. Maskey 		return ("conditions for activation are unmet");
4256ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_MANUAL_DISABLE:
4266ba597c5SAnurag S. Maskey 		return ("disabled by administrator");
4276ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_METHOD_FAILED:
4286ba597c5SAnurag S. Maskey 		return ("method/service failed");
4296ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_METHOD_MISSING:
4306ba597c5SAnurag S. Maskey 		return ("method or FMRI not specified");
4316ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_INVALID_CONFIG:
4326ba597c5SAnurag S. Maskey 		return ("invalid configuration values");
4336ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_METHOD_RUNNING:
4346ba597c5SAnurag S. Maskey 		return ("method/service executing");
4356ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_ACTIVE:
4366ba597c5SAnurag S. Maskey 		return ("active");
4376ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_SCANNING:
4386ba597c5SAnurag S. Maskey 		return ("scanning for WiFi networks");
4396ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_NEED_SELECTION:
4406ba597c5SAnurag S. Maskey 		return ("need WiFi network selection");
4416ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_NEED_KEY:
4426ba597c5SAnurag S. Maskey 		return ("need WiFi security key");
4436ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_LINK_WIFI_CONNECTING:
4446ba597c5SAnurag S. Maskey 		return ("connecting to WiFi network");
4456ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_IF_WAITING_FOR_ADDR:
4466ba597c5SAnurag S. Maskey 		return ("waiting for IP address to be set");
4476ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_IF_DHCP_TIMED_OUT:
4486ba597c5SAnurag S. Maskey 		return ("DHCP wait timeout, still trying...");
4496ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_IF_DUPLICATE_ADDR:
4506ba597c5SAnurag S. Maskey 		return ("duplicate address detected");
4516ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_UP:
4526ba597c5SAnurag S. Maskey 		return ("interface/link is up");
4536ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_DOWN:
4546ba597c5SAnurag S. Maskey 		return ("interface/link is down");
4556ba597c5SAnurag S. Maskey 	case NWAM_AUX_STATE_NOT_FOUND:
4566ba597c5SAnurag S. Maskey 		return ("interface/link not found");
4576ba597c5SAnurag S. Maskey 	default:
4586ba597c5SAnurag S. Maskey 		return ("unknown");
4596ba597c5SAnurag S. Maskey 	}
4606ba597c5SAnurag S. Maskey }
4616ba597c5SAnurag S. Maskey 
4626ba597c5SAnurag S. Maskey const char *
4636ba597c5SAnurag S. Maskey nwam_object_type_to_string(nwam_object_type_t type)
4646ba597c5SAnurag S. Maskey {
4656ba597c5SAnurag S. Maskey 	switch (type) {
4666ba597c5SAnurag S. Maskey 	case NWAM_OBJECT_TYPE_NCP:
4676ba597c5SAnurag S. Maskey 		return ("ncp");
4686ba597c5SAnurag S. Maskey 	case NWAM_OBJECT_TYPE_NCU:
4696ba597c5SAnurag S. Maskey 		return ("ncu");
4706ba597c5SAnurag S. Maskey 	case NWAM_OBJECT_TYPE_LOC:
4716ba597c5SAnurag S. Maskey 		return ("loc");
4726ba597c5SAnurag S. Maskey 	case NWAM_OBJECT_TYPE_ENM:
4736ba597c5SAnurag S. Maskey 		return ("enm");
4746ba597c5SAnurag S. Maskey 	case NWAM_OBJECT_TYPE_KNOWN_WLAN:
4756ba597c5SAnurag S. Maskey 		return ("known wlan");
4766ba597c5SAnurag S. Maskey 	default:
4776ba597c5SAnurag S. Maskey 		return ("unknown");
4786ba597c5SAnurag S. Maskey 	}
4796ba597c5SAnurag S. Maskey }
4806ba597c5SAnurag S. Maskey 
4816ba597c5SAnurag S. Maskey nwam_object_type_t
4826ba597c5SAnurag S. Maskey nwam_string_to_object_type(const char *typestr)
4836ba597c5SAnurag S. Maskey {
4846ba597c5SAnurag S. Maskey 	if (strcasecmp(typestr,
4856ba597c5SAnurag S. Maskey 	    nwam_object_type_to_string(NWAM_OBJECT_TYPE_NCP)) == 0)
4866ba597c5SAnurag S. Maskey 		return (NWAM_OBJECT_TYPE_NCP);
4876ba597c5SAnurag S. Maskey 	if (strcasecmp(typestr,
4886ba597c5SAnurag S. Maskey 	    nwam_object_type_to_string(NWAM_OBJECT_TYPE_NCU)) == 0)
4896ba597c5SAnurag S. Maskey 		return (NWAM_OBJECT_TYPE_NCU);
4906ba597c5SAnurag S. Maskey 	if (strcasecmp(typestr,
4916ba597c5SAnurag S. Maskey 	    nwam_object_type_to_string(NWAM_OBJECT_TYPE_LOC)) == 0)
4926ba597c5SAnurag S. Maskey 		return (NWAM_OBJECT_TYPE_LOC);
4936ba597c5SAnurag S. Maskey 	if (strcasecmp(typestr,
4946ba597c5SAnurag S. Maskey 	    nwam_object_type_to_string(NWAM_OBJECT_TYPE_ENM)) == 0)
4956ba597c5SAnurag S. Maskey 		return (NWAM_OBJECT_TYPE_ENM);
4966ba597c5SAnurag S. Maskey 	if (strcasecmp(typestr,
4976ba597c5SAnurag S. Maskey 	    nwam_object_type_to_string(NWAM_OBJECT_TYPE_KNOWN_WLAN)) == 0)
4986ba597c5SAnurag S. Maskey 		return (NWAM_OBJECT_TYPE_KNOWN_WLAN);
4996ba597c5SAnurag S. Maskey 	return (NWAM_OBJECT_TYPE_UNKNOWN);
5006ba597c5SAnurag S. Maskey }
5016ba597c5SAnurag S. Maskey 
5026ba597c5SAnurag S. Maskey nwam_error_t
5036ba597c5SAnurag S. Maskey nwam_errno_to_nwam_error(int errnum)
5046ba597c5SAnurag S. Maskey {
5056ba597c5SAnurag S. Maskey 	switch (errnum) {
5066ba597c5SAnurag S. Maskey 	case 0:
5076ba597c5SAnurag S. Maskey 		return (NWAM_SUCCESS);
5086ba597c5SAnurag S. Maskey 	case EBADF:
5096ba597c5SAnurag S. Maskey 		return (NWAM_ERROR_BIND);
5106ba597c5SAnurag S. Maskey 	case EPERM:
5116ba597c5SAnurag S. Maskey 	case EACCES:
5126ba597c5SAnurag S. Maskey 		return (NWAM_PERMISSION_DENIED);
5136ba597c5SAnurag S. Maskey 	case ENOENT:
5146ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_NOT_FOUND);
5156ba597c5SAnurag S. Maskey 	case EIDRM:
5166ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID);
5176ba597c5SAnurag S. Maskey 	case EEXIST:
5186ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_EXISTS);
5196ba597c5SAnurag S. Maskey 	case EAGAIN:
5206ba597c5SAnurag S. Maskey 	case EBUSY:
5216ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_IN_USE);
5226ba597c5SAnurag S. Maskey 	case ENOMEM:
5236ba597c5SAnurag S. Maskey 	case ENOSPC:
5246ba597c5SAnurag S. Maskey 		return (NWAM_NO_MEMORY);
5256ba597c5SAnurag S. Maskey 	case EINVAL:
5266ba597c5SAnurag S. Maskey 	case E2BIG:
5276ba597c5SAnurag S. Maskey 		return (NWAM_INVALID_ARG);
5286ba597c5SAnurag S. Maskey 	default:
5296ba597c5SAnurag S. Maskey 		return (NWAM_ERROR_INTERNAL);
5306ba597c5SAnurag S. Maskey 	}
5316ba597c5SAnurag S. Maskey }
5326ba597c5SAnurag S. Maskey 
5336ba597c5SAnurag S. Maskey /* Common validation functions */
5346ba597c5SAnurag S. Maskey 
5356ba597c5SAnurag S. Maskey /*
5366ba597c5SAnurag S. Maskey  * Do the flags represent a subset of valid_flags?
5376ba597c5SAnurag S. Maskey  */
5386ba597c5SAnurag S. Maskey nwam_error_t
5396ba597c5SAnurag S. Maskey nwam_valid_flags(uint64_t flags, uint64_t valid_flags)
5406ba597c5SAnurag S. Maskey {
5416ba597c5SAnurag S. Maskey 
5426ba597c5SAnurag S. Maskey 	if ((flags | valid_flags) != valid_flags)
5436ba597c5SAnurag S. Maskey 		return (NWAM_INVALID_ARG);
5446ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
5456ba597c5SAnurag S. Maskey }
5466ba597c5SAnurag S. Maskey 
5476ba597c5SAnurag S. Maskey nwam_error_t
5486ba597c5SAnurag S. Maskey nwam_valid_condition(nwam_value_t value)
5496ba597c5SAnurag S. Maskey {
5506ba597c5SAnurag S. Maskey 	char **conditions;
5516ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
5526ba597c5SAnurag S. Maskey 	nwam_condition_object_type_t object_type;
5536ba597c5SAnurag S. Maskey 	nwam_condition_t condition;
5546ba597c5SAnurag S. Maskey 
5556ba597c5SAnurag S. Maskey 	if (nwam_value_get_string_array(value, &conditions, &numvalues)
5566ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
5576ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
5586ba597c5SAnurag S. Maskey 
5596ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
5606ba597c5SAnurag S. Maskey 		char *object_name = NULL;
5616ba597c5SAnurag S. Maskey 
5626ba597c5SAnurag S. Maskey 		if (nwam_condition_string_to_condition(conditions[i],
5636ba597c5SAnurag S. Maskey 		    &object_type, &condition, &object_name) != NWAM_SUCCESS)
5646ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
5656ba597c5SAnurag S. Maskey 		if (object_name != NULL)
5666ba597c5SAnurag S. Maskey 			free(object_name);
5676ba597c5SAnurag S. Maskey 	}
5686ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
5696ba597c5SAnurag S. Maskey }
5706ba597c5SAnurag S. Maskey 
5716ba597c5SAnurag S. Maskey /* check if boolean values are correct, generalize for array of booleans */
5726ba597c5SAnurag S. Maskey nwam_error_t
5736ba597c5SAnurag S. Maskey nwam_valid_boolean(nwam_value_t value)
5746ba597c5SAnurag S. Maskey {
5756ba597c5SAnurag S. Maskey 	boolean_t *val;
5766ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
5776ba597c5SAnurag S. Maskey 
5786ba597c5SAnurag S. Maskey 	if (nwam_value_get_boolean_array(value, &val, &numvalues)
5796ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
5806ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
5816ba597c5SAnurag S. Maskey 
5826ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
5836ba597c5SAnurag S. Maskey 		if (val[i] != B_TRUE && val[i] != B_FALSE)
5846ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
5856ba597c5SAnurag S. Maskey 	}
5866ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
5876ba597c5SAnurag S. Maskey }
5886ba597c5SAnurag S. Maskey 
5896ba597c5SAnurag S. Maskey /* check if uint64 values are correct, generalize for array of ints */
5906ba597c5SAnurag S. Maskey nwam_error_t
5916ba597c5SAnurag S. Maskey nwam_valid_uint64(nwam_value_t value)
5926ba597c5SAnurag S. Maskey {
5936ba597c5SAnurag S. Maskey 	int64_t *val;
5946ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
5956ba597c5SAnurag S. Maskey 
5966ba597c5SAnurag S. Maskey 	if (nwam_value_get_int64_array(value, &val, &numvalues)
5976ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
5986ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
5996ba597c5SAnurag S. Maskey 
6006ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
6016ba597c5SAnurag S. Maskey 		if (val[i] < 0)
6026ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
6036ba597c5SAnurag S. Maskey 	}
6046ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
6056ba597c5SAnurag S. Maskey }
6066ba597c5SAnurag S. Maskey 
6076ba597c5SAnurag S. Maskey /* check if domain names are correct, generalize for array of domains */
6086ba597c5SAnurag S. Maskey nwam_error_t
6096ba597c5SAnurag S. Maskey nwam_valid_domain(nwam_value_t value)
6106ba597c5SAnurag S. Maskey {
6116ba597c5SAnurag S. Maskey 	char **domainvalues, *domain;
6126ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
6136ba597c5SAnurag S. Maskey 	int len, j;
6146ba597c5SAnurag S. Maskey 
6156ba597c5SAnurag S. Maskey 	if (nwam_value_get_string_array(value, &domainvalues, &numvalues)
6166ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
6176ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
6186ba597c5SAnurag S. Maskey 
6196ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
6206ba597c5SAnurag S. Maskey 		/*
6216ba597c5SAnurag S. Maskey 		 * First and last character must be alphanumeric.
6226ba597c5SAnurag S. Maskey 		 * Only '.' and '-' are allowed.
6236ba597c5SAnurag S. Maskey 		 */
6246ba597c5SAnurag S. Maskey 		domain = domainvalues[i];
6256ba597c5SAnurag S. Maskey 		len = strlen(domain);
6266ba597c5SAnurag S. Maskey 		if (!isalnum(domain[0]) || !isalnum(domain[len-1]))
6276ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
6286ba597c5SAnurag S. Maskey 		for (j = 0; j < len; j++) {
6296ba597c5SAnurag S. Maskey 			if (!isalnum(domain[j]) &&
6306ba597c5SAnurag S. Maskey 			    domain[j] != '.' && domain[j] != '-')
6316ba597c5SAnurag S. Maskey 				return (NWAM_ENTITY_INVALID_VALUE);
6326ba597c5SAnurag S. Maskey 		}
6336ba597c5SAnurag S. Maskey 	}
6346ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
6356ba597c5SAnurag S. Maskey }
6366ba597c5SAnurag S. Maskey 
6376ba597c5SAnurag S. Maskey /* check if address prefix is valid */
6386ba597c5SAnurag S. Maskey static nwam_error_t
6396ba597c5SAnurag S. Maskey nwam_valid_prefix(char *addr, int max_plen)
6406ba597c5SAnurag S. Maskey {
6416ba597c5SAnurag S. Maskey 	char *prefix, *end;
6426ba597c5SAnurag S. Maskey 	int prefixlen;
6436ba597c5SAnurag S. Maskey 
6446ba597c5SAnurag S. Maskey 	if ((prefix = strchr(addr, '/')) != NULL) {
6456ba597c5SAnurag S. Maskey 		prefix++;
6466ba597c5SAnurag S. Maskey 		prefixlen = strtol(prefix, &end, 10);
6476ba597c5SAnurag S. Maskey 		if (prefix == end || prefixlen < 0 || prefixlen > max_plen)
6486ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
6496ba597c5SAnurag S. Maskey 	}
6506ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
6516ba597c5SAnurag S. Maskey }
6526ba597c5SAnurag S. Maskey 
6536ba597c5SAnurag S. Maskey /* check if IPv4 addresses are correct, generalize for array of addresses */
6546ba597c5SAnurag S. Maskey nwam_error_t
6556ba597c5SAnurag S. Maskey nwam_valid_host_v4(nwam_value_t value)
6566ba597c5SAnurag S. Maskey {
6576ba597c5SAnurag S. Maskey 	char **addrvalues, *addr;
6586ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
6596ba597c5SAnurag S. Maskey 	struct sockaddr_in sa;
6606ba597c5SAnurag S. Maskey 
6616ba597c5SAnurag S. Maskey 	if (nwam_value_get_string_array(value, &addrvalues, &numvalues)
6626ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
6636ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
6646ba597c5SAnurag S. Maskey 
6656ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
6666ba597c5SAnurag S. Maskey 		addr = strdup(addrvalues[i]);
6676ba597c5SAnurag S. Maskey 		if (nwam_valid_prefix(addr, IP_ABITS) != NWAM_SUCCESS) {
6686ba597c5SAnurag S. Maskey 			free(addr);
6696ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
6706ba597c5SAnurag S. Maskey 		}
6716ba597c5SAnurag S. Maskey 		/* replace '/' with '\0' */
6726ba597c5SAnurag S. Maskey 		addr = strsep(&addr, "/");
6736ba597c5SAnurag S. Maskey 		if (inet_pton(AF_INET, addr, &(sa.sin_addr)) != 1) {
6746ba597c5SAnurag S. Maskey 			free(addr);
6756ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
6766ba597c5SAnurag S. Maskey 		}
6776ba597c5SAnurag S. Maskey 		free(addr);
6786ba597c5SAnurag S. Maskey 	}
6796ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
6806ba597c5SAnurag S. Maskey }
6816ba597c5SAnurag S. Maskey 
6826ba597c5SAnurag S. Maskey /* Check if IPv4 address for default route is valid */
6836ba597c5SAnurag S. Maskey nwam_error_t
6846ba597c5SAnurag S. Maskey nwam_valid_route_v4(nwam_value_t value)
6856ba597c5SAnurag S. Maskey {
6866ba597c5SAnurag S. Maskey 	char *addrvalue;
6876ba597c5SAnurag S. Maskey 	struct sockaddr_in sa;
6886ba597c5SAnurag S. Maskey 
6896ba597c5SAnurag S. Maskey 	if (nwam_value_get_string(value, &addrvalue) != NWAM_SUCCESS)
6906ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
6916ba597c5SAnurag S. Maskey 
6926ba597c5SAnurag S. Maskey 	if (inet_pton(AF_INET, addrvalue, &(sa.sin_addr)) != 1)
6936ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
6946ba597c5SAnurag S. Maskey 
6956ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
6966ba597c5SAnurag S. Maskey }
6976ba597c5SAnurag S. Maskey 
6986ba597c5SAnurag S. Maskey /* check if IPv6 addresses are correct, generalize for array of addresses */
6996ba597c5SAnurag S. Maskey nwam_error_t
7006ba597c5SAnurag S. Maskey nwam_valid_host_v6(nwam_value_t value)
7016ba597c5SAnurag S. Maskey {
7026ba597c5SAnurag S. Maskey 	char **addrvalues, *addr;
7036ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
7046ba597c5SAnurag S. Maskey 	struct sockaddr_in6 sa;
7056ba597c5SAnurag S. Maskey 
7066ba597c5SAnurag S. Maskey 	if (nwam_value_get_string_array(value, &addrvalues, &numvalues)
7076ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
7086ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
7096ba597c5SAnurag S. Maskey 
7106ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
7116ba597c5SAnurag S. Maskey 		addr = strdup(addrvalues[i]);
7126ba597c5SAnurag S. Maskey 		if (nwam_valid_prefix(addr, IPV6_ABITS) != NWAM_SUCCESS) {
7136ba597c5SAnurag S. Maskey 			free(addr);
7146ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
7156ba597c5SAnurag S. Maskey 		}
7166ba597c5SAnurag S. Maskey 		/* replace '/' with '\0' */
7176ba597c5SAnurag S. Maskey 		addr = strsep(&addr, "/");
7186ba597c5SAnurag S. Maskey 		if (inet_pton(AF_INET6, addr, &(sa.sin6_addr)) != 1) {
7196ba597c5SAnurag S. Maskey 			free(addr);
7206ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
7216ba597c5SAnurag S. Maskey 		}
7226ba597c5SAnurag S. Maskey 		free(addr);
7236ba597c5SAnurag S. Maskey 	}
7246ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
7256ba597c5SAnurag S. Maskey }
7266ba597c5SAnurag S. Maskey 
7276ba597c5SAnurag S. Maskey /* Check if IPv4 address for default route is valid */
7286ba597c5SAnurag S. Maskey nwam_error_t
7296ba597c5SAnurag S. Maskey nwam_valid_route_v6(nwam_value_t value)
7306ba597c5SAnurag S. Maskey {
7316ba597c5SAnurag S. Maskey 	char *addrvalue;
7326ba597c5SAnurag S. Maskey 	struct sockaddr_in6 sa;
7336ba597c5SAnurag S. Maskey 
7346ba597c5SAnurag S. Maskey 	if (nwam_value_get_string(value, &addrvalue) != NWAM_SUCCESS)
7356ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
7366ba597c5SAnurag S. Maskey 
7376ba597c5SAnurag S. Maskey 	if (inet_pton(AF_INET6, addrvalue, &(sa.sin6_addr)) != 1)
7386ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
7396ba597c5SAnurag S. Maskey 
7406ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
7416ba597c5SAnurag S. Maskey }
7426ba597c5SAnurag S. Maskey 
7436ba597c5SAnurag S. Maskey nwam_error_t
7446ba597c5SAnurag S. Maskey nwam_valid_host_any(nwam_value_t value)
7456ba597c5SAnurag S. Maskey {
7466ba597c5SAnurag S. Maskey 	if (nwam_valid_host_v4(value) != NWAM_SUCCESS &&
7476ba597c5SAnurag S. Maskey 	    nwam_valid_host_v6(value) != NWAM_SUCCESS)
7486ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
7496ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
7506ba597c5SAnurag S. Maskey }
7516ba597c5SAnurag S. Maskey 
7526ba597c5SAnurag S. Maskey nwam_error_t
7536ba597c5SAnurag S. Maskey nwam_valid_host_or_domain(nwam_value_t value)
7546ba597c5SAnurag S. Maskey {
7556ba597c5SAnurag S. Maskey 	if (nwam_valid_host_any(value) != NWAM_SUCCESS &&
7566ba597c5SAnurag S. Maskey 	    nwam_valid_domain(value) != NWAM_SUCCESS)
7576ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
7586ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
7596ba597c5SAnurag S. Maskey }
7606ba597c5SAnurag S. Maskey 
7616ba597c5SAnurag S. Maskey /* We do not validate file existence, merely that it is an absolute path. */
7626ba597c5SAnurag S. Maskey nwam_error_t
7636ba597c5SAnurag S. Maskey nwam_valid_file(nwam_value_t value)
7646ba597c5SAnurag S. Maskey {
7656ba597c5SAnurag S. Maskey 	char **files;
7666ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
7676ba597c5SAnurag S. Maskey 
7686ba597c5SAnurag S. Maskey 	if (nwam_value_get_string_array(value, &files, &numvalues)
7696ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
7706ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
7716ba597c5SAnurag S. Maskey 
7726ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
7736ba597c5SAnurag S. Maskey 		int j = 0;
7746ba597c5SAnurag S. Maskey 		while (isspace(files[i][j]))
7756ba597c5SAnurag S. Maskey 			j++;
7766ba597c5SAnurag S. Maskey 		if (files[i][j] != '/')
7776ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
7786ba597c5SAnurag S. Maskey 	}
7796ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
7806ba597c5SAnurag S. Maskey }
7816ba597c5SAnurag S. Maskey 
7826ba597c5SAnurag S. Maskey /*
7836ba597c5SAnurag S. Maskey  * We do not validate existence of the object pointed to by the FMRI
7846ba597c5SAnurag S. Maskey  * but merely ensure that it is a valid FMRI.  We do this by
7856ba597c5SAnurag S. Maskey  * using scf_handle_decode_fmri(), but ignore all errors bar
7866ba597c5SAnurag S. Maskey  * SCF_ERROR_INVALID_ARGUMENT (which indicates the FMRI is invalid).
7876ba597c5SAnurag S. Maskey  */
7886ba597c5SAnurag S. Maskey nwam_error_t
7896ba597c5SAnurag S. Maskey nwam_valid_fmri(nwam_value_t value)
7906ba597c5SAnurag S. Maskey {
7916ba597c5SAnurag S. Maskey 	char **valstr;
7926ba597c5SAnurag S. Maskey 	scf_handle_t *h = NULL;
7936ba597c5SAnurag S. Maskey 	scf_service_t *svc = NULL;
7946ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
7956ba597c5SAnurag S. Maskey 	nwam_error_t err = NWAM_SUCCESS;
7966ba597c5SAnurag S. Maskey 
7976ba597c5SAnurag S. Maskey 	if ((err = nwam_value_get_string_array(value, &valstr, &numvalues))
7986ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
7996ba597c5SAnurag S. Maskey 		return (err);
8006ba597c5SAnurag S. Maskey 
8016ba597c5SAnurag S. Maskey 	h = scf_handle_create(SCF_VERSION);
8026ba597c5SAnurag S. Maskey 	if (h == NULL)
8036ba597c5SAnurag S. Maskey 		return (NWAM_ERROR_INTERNAL);
8046ba597c5SAnurag S. Maskey 
8056ba597c5SAnurag S. Maskey 	if (scf_handle_bind(h) != 0) {
8066ba597c5SAnurag S. Maskey 		err = NWAM_ERROR_INTERNAL;
8076ba597c5SAnurag S. Maskey 		goto out;
8086ba597c5SAnurag S. Maskey 	}
8096ba597c5SAnurag S. Maskey 
8106ba597c5SAnurag S. Maskey 	if ((svc = scf_service_create(h)) == NULL) {
8116ba597c5SAnurag S. Maskey 		err = NWAM_ERROR_INTERNAL;
8126ba597c5SAnurag S. Maskey 		goto out;
8136ba597c5SAnurag S. Maskey 	}
8146ba597c5SAnurag S. Maskey 
8156ba597c5SAnurag S. Maskey 
8166ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
8176ba597c5SAnurag S. Maskey 		if (scf_handle_decode_fmri(h, valstr[i], NULL, svc,
8186ba597c5SAnurag S. Maskey 		    NULL, NULL, NULL, SCF_DECODE_FMRI_TRUNCATE) == 0 ||
8196ba597c5SAnurag S. Maskey 		    scf_error() != SCF_ERROR_INVALID_ARGUMENT) {
8206ba597c5SAnurag S. Maskey 			err = NWAM_SUCCESS;
8216ba597c5SAnurag S. Maskey 			continue;
8226ba597c5SAnurag S. Maskey 		}
8236ba597c5SAnurag S. Maskey 		err = NWAM_ENTITY_INVALID_VALUE;
8246ba597c5SAnurag S. Maskey 		break;
8256ba597c5SAnurag S. Maskey 	}
8266ba597c5SAnurag S. Maskey out:
8276ba597c5SAnurag S. Maskey 	scf_service_destroy(svc);
8286ba597c5SAnurag S. Maskey 	scf_handle_destroy(h);
8296ba597c5SAnurag S. Maskey 	return (err);
8306ba597c5SAnurag S. Maskey }
8316ba597c5SAnurag S. Maskey 
8326ba597c5SAnurag S. Maskey /* verifies mac-address and bssids */
8336ba597c5SAnurag S. Maskey nwam_error_t
8346ba597c5SAnurag S. Maskey nwam_valid_mac_addr(nwam_value_t value)
8356ba597c5SAnurag S. Maskey {
8366ba597c5SAnurag S. Maskey 	char **mac_addrs, *addr;
8376ba597c5SAnurag S. Maskey 	uchar_t	*hwaddr;
8386ba597c5SAnurag S. Maskey 	int hwaddrlen, j;
8396ba597c5SAnurag S. Maskey 	uint_t i, numvalues;
8406ba597c5SAnurag S. Maskey 
8416ba597c5SAnurag S. Maskey 	if (nwam_value_get_string_array(value, &mac_addrs, &numvalues)
8426ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS)
8436ba597c5SAnurag S. Maskey 		return (NWAM_ENTITY_INVALID_VALUE);
8446ba597c5SAnurag S. Maskey 
8456ba597c5SAnurag S. Maskey 	for (i = 0; i < numvalues; i++) {
8466ba597c5SAnurag S. Maskey 		addr = mac_addrs[i];
8476ba597c5SAnurag S. Maskey 		j = 0;
8486ba597c5SAnurag S. Maskey 
8496ba597c5SAnurag S. Maskey 		/* validate that a-fA-F0-9 and ':' only */
8506ba597c5SAnurag S. Maskey 		while (addr[j] != 0) {
8516ba597c5SAnurag S. Maskey 			if (!isxdigit(addr[j]) && addr[j] != ':')
8526ba597c5SAnurag S. Maskey 				return (NWAM_ENTITY_INVALID_VALUE);
8536ba597c5SAnurag S. Maskey 			j++;
8546ba597c5SAnurag S. Maskey 		}
8556ba597c5SAnurag S. Maskey 
8566ba597c5SAnurag S. Maskey 		if ((hwaddr = _link_aton(addr, &hwaddrlen)) == NULL)
8576ba597c5SAnurag S. Maskey 			return (NWAM_ENTITY_INVALID_VALUE);
8586ba597c5SAnurag S. Maskey 		free(hwaddr);
8596ba597c5SAnurag S. Maskey 	}
8606ba597c5SAnurag S. Maskey 
8616ba597c5SAnurag S. Maskey 	return (NWAM_SUCCESS);
8626ba597c5SAnurag S. Maskey }
8636ba597c5SAnurag S. Maskey 
8646ba597c5SAnurag S. Maskey boolean_t
865*69b43529SMichael Hunter nwam_uid_is_special(void)
8666ba597c5SAnurag S. Maskey {
867*69b43529SMichael Hunter 	uid_t uid = getuid();
868*69b43529SMichael Hunter 	return (uid == UID_NETADM || uid == 0);
8696ba597c5SAnurag S. Maskey }
8706ba597c5SAnurag S. Maskey 
8716ba597c5SAnurag S. Maskey nwam_error_t
8726ba597c5SAnurag S. Maskey nwam_get_smf_string_property(const char *fmri, const char *pgname,
8736ba597c5SAnurag S. Maskey     const char *propname, char **valuep)
8746ba597c5SAnurag S. Maskey {
8756ba597c5SAnurag S. Maskey 	scf_handle_t *h = NULL;
8766ba597c5SAnurag S. Maskey 	scf_snapshot_t *snap = NULL;
8776ba597c5SAnurag S. Maskey 	scf_instance_t *inst = NULL;
8786ba597c5SAnurag S. Maskey 	scf_propertygroup_t *pg = NULL;
8796ba597c5SAnurag S. Maskey 	scf_property_t *prop = NULL;
8806ba597c5SAnurag S. Maskey 	scf_value_t *val = NULL;
8816ba597c5SAnurag S. Maskey 	nwam_error_t err = NWAM_SUCCESS;
8826ba597c5SAnurag S. Maskey 
8836ba597c5SAnurag S. Maskey 	if ((*valuep = malloc(NWAM_MAX_NAME_LEN)) == NULL)
8846ba597c5SAnurag S. Maskey 		return (NWAM_NO_MEMORY);
8856ba597c5SAnurag S. Maskey 
8866ba597c5SAnurag S. Maskey 	if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
8876ba597c5SAnurag S. Maskey 	    scf_handle_bind(h) != 0 ||
8886ba597c5SAnurag S. Maskey 	    (inst = scf_instance_create(h)) == NULL ||
8896ba597c5SAnurag S. Maskey 	    (snap = scf_snapshot_create(h)) == NULL ||
8906ba597c5SAnurag S. Maskey 	    (pg = scf_pg_create(h)) == NULL ||
8916ba597c5SAnurag S. Maskey 	    (prop = scf_property_create(h)) == NULL ||
8926ba597c5SAnurag S. Maskey 	    (val = scf_value_create(h)) == NULL) {
8936ba597c5SAnurag S. Maskey 		err = NWAM_ERROR_INTERNAL;
8946ba597c5SAnurag S. Maskey 		goto out;
8956ba597c5SAnurag S. Maskey 	}
8966ba597c5SAnurag S. Maskey 	if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst,
8976ba597c5SAnurag S. Maskey 	    NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) {
8986ba597c5SAnurag S. Maskey 		err = NWAM_ENTITY_NOT_FOUND;
8996ba597c5SAnurag S. Maskey 		goto out;
9006ba597c5SAnurag S. Maskey 	}
9016ba597c5SAnurag S. Maskey 	/* Retrieve value from running snapshot (if present) */
9026ba597c5SAnurag S. Maskey 	if (scf_instance_get_snapshot(inst, "running", snap) != 0) {
9036ba597c5SAnurag S. Maskey 		scf_snapshot_destroy(snap);
9046ba597c5SAnurag S. Maskey 		snap = NULL;
9056ba597c5SAnurag S. Maskey 	}
9066ba597c5SAnurag S. Maskey 	if (scf_instance_get_pg_composed(inst, snap, pgname, pg) != 0 ||
9076ba597c5SAnurag S. Maskey 	    scf_pg_get_property(pg, propname, prop) != 0 ||
9086ba597c5SAnurag S. Maskey 	    scf_property_get_value(prop, val) != 0 ||
9096ba597c5SAnurag S. Maskey 	    scf_value_get_astring(val, *valuep, NWAM_MAX_NAME_LEN) == -1) {
9106ba597c5SAnurag S. Maskey 		err = NWAM_ENTITY_NOT_FOUND;
9116ba597c5SAnurag S. Maskey 	}
9126ba597c5SAnurag S. Maskey out:
9136ba597c5SAnurag S. Maskey 	if (err != NWAM_SUCCESS)
9146ba597c5SAnurag S. Maskey 		free(*valuep);
9156ba597c5SAnurag S. Maskey 
9166ba597c5SAnurag S. Maskey 	scf_value_destroy(val);
9176ba597c5SAnurag S. Maskey 	scf_property_destroy(prop);
9186ba597c5SAnurag S. Maskey 	scf_pg_destroy(pg);
9196ba597c5SAnurag S. Maskey 	if (snap != NULL)
9206ba597c5SAnurag S. Maskey 		scf_snapshot_destroy(snap);
9216ba597c5SAnurag S. Maskey 	scf_instance_destroy(inst);
9226ba597c5SAnurag S. Maskey 	scf_handle_destroy(h);
9236ba597c5SAnurag S. Maskey 
9246ba597c5SAnurag S. Maskey 	return (err);
9256ba597c5SAnurag S. Maskey }
9266ba597c5SAnurag S. Maskey 
9276ba597c5SAnurag S. Maskey nwam_error_t
9286ba597c5SAnurag S. Maskey nwam_set_smf_string_property(const char *fmri, const char *pgname,
9296ba597c5SAnurag S. Maskey     const char *propname, const char *propval)
9306ba597c5SAnurag S. Maskey {
9316ba597c5SAnurag S. Maskey 	scf_handle_t *h = NULL;
9326ba597c5SAnurag S. Maskey 	scf_instance_t *inst = NULL;
9336ba597c5SAnurag S. Maskey 	scf_propertygroup_t *pg = NULL;
9346ba597c5SAnurag S. Maskey 	scf_property_t *prop = NULL;
9356ba597c5SAnurag S. Maskey 	scf_value_t *val = NULL;
9366ba597c5SAnurag S. Maskey 	scf_transaction_t *tx = NULL;
9376ba597c5SAnurag S. Maskey 	scf_transaction_entry_t *ent = NULL;
9386ba597c5SAnurag S. Maskey 	nwam_error_t err = NWAM_SUCCESS;
9396ba597c5SAnurag S. Maskey 	int result;
9406ba597c5SAnurag S. Maskey 
9416ba597c5SAnurag S. Maskey 	if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
9426ba597c5SAnurag S. Maskey 	    scf_handle_bind(h) != 0 ||
9436ba597c5SAnurag S. Maskey 	    (inst = scf_instance_create(h)) == NULL ||
9446ba597c5SAnurag S. Maskey 	    (pg = scf_pg_create(h)) == NULL ||
9456ba597c5SAnurag S. Maskey 	    (prop = scf_property_create(h)) == NULL ||
9466ba597c5SAnurag S. Maskey 	    (val = scf_value_create(h)) == NULL ||
9476ba597c5SAnurag S. Maskey 	    scf_value_set_astring(val, propval) != 0 ||
9486ba597c5SAnurag S. Maskey 	    (tx = scf_transaction_create(h)) == NULL ||
9496ba597c5SAnurag S. Maskey 	    (ent = scf_entry_create(h)) == NULL) {
9506ba597c5SAnurag S. Maskey 		err = NWAM_ERROR_INTERNAL;
9516ba597c5SAnurag S. Maskey 		goto out;
9526ba597c5SAnurag S. Maskey 	}
9536ba597c5SAnurag S. Maskey 	if (scf_handle_decode_fmri(h, fmri, NULL, NULL, inst,
9546ba597c5SAnurag S. Maskey 	    NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0 ||
9556ba597c5SAnurag S. Maskey 	    scf_instance_get_pg_composed(inst, NULL, pgname, pg) != 0) {
9566ba597c5SAnurag S. Maskey 		err = NWAM_ENTITY_NOT_FOUND;
9576ba597c5SAnurag S. Maskey 		goto out;
9586ba597c5SAnurag S. Maskey 	}
9596ba597c5SAnurag S. Maskey 
9606ba597c5SAnurag S. Maskey retry:
9616ba597c5SAnurag S. Maskey 	if (scf_transaction_start(tx, pg) == -1 ||
9626ba597c5SAnurag S. Maskey 	    scf_transaction_property_change(tx, ent, propname, SCF_TYPE_ASTRING)
9636ba597c5SAnurag S. Maskey 	    == -1 || scf_entry_add_value(ent, val) != 0) {
9646ba597c5SAnurag S. Maskey 		err = NWAM_ERROR_INTERNAL;
9656ba597c5SAnurag S. Maskey 		goto out;
9666ba597c5SAnurag S. Maskey 	}
9676ba597c5SAnurag S. Maskey 
9686ba597c5SAnurag S. Maskey 	result = scf_transaction_commit(tx);
9696ba597c5SAnurag S. Maskey 	switch (result) {
9706ba597c5SAnurag S. Maskey 	case 1:
9716ba597c5SAnurag S. Maskey 		(void) smf_refresh_instance(fmri);
9726ba597c5SAnurag S. Maskey 		break;
9736ba597c5SAnurag S. Maskey 	case 0:
9746ba597c5SAnurag S. Maskey 		scf_transaction_reset(tx);
9756ba597c5SAnurag S. Maskey 		if (scf_pg_update(pg) == -1) {
9766ba597c5SAnurag S. Maskey 			err = NWAM_ERROR_INTERNAL;
9776ba597c5SAnurag S. Maskey 			goto out;
9786ba597c5SAnurag S. Maskey 		}
9796ba597c5SAnurag S. Maskey 		goto retry;
9806ba597c5SAnurag S. Maskey 	default:
9816ba597c5SAnurag S. Maskey 		err = NWAM_ERROR_INTERNAL;
9826ba597c5SAnurag S. Maskey 		break;
9836ba597c5SAnurag S. Maskey 	}
9846ba597c5SAnurag S. Maskey out:
9856ba597c5SAnurag S. Maskey 	scf_value_destroy(val);
9866ba597c5SAnurag S. Maskey 	scf_property_destroy(prop);
9876ba597c5SAnurag S. Maskey 	scf_pg_destroy(pg);
9886ba597c5SAnurag S. Maskey 	scf_instance_destroy(inst);
9896ba597c5SAnurag S. Maskey 	scf_handle_destroy(h);
9906ba597c5SAnurag S. Maskey 
9916ba597c5SAnurag S. Maskey 	return (err);
9926ba597c5SAnurag S. Maskey }
993