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 /*
23*f6da83d4SAnurag S. Maskey  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
246ba597c5SAnurag S. Maskey  */
256ba597c5SAnurag S. Maskey 
266ba597c5SAnurag S. Maskey #include <arpa/inet.h>
276ba597c5SAnurag S. Maskey #include <ctype.h>
286ba597c5SAnurag S. Maskey #include <errno.h>
296ba597c5SAnurag S. Maskey #include <inet/ip.h>
306ba597c5SAnurag S. Maskey #include <libdladm.h>
316ba597c5SAnurag S. Maskey #include <libdllink.h>
326ba597c5SAnurag S. Maskey #include <libdlwlan.h>
336ba597c5SAnurag S. Maskey #include <netdb.h>
346ba597c5SAnurag S. Maskey #include <stdio.h>
356ba597c5SAnurag S. Maskey #include <stdlib.h>
366ba597c5SAnurag S. Maskey #include <string.h>
376ba597c5SAnurag S. Maskey 
386ba597c5SAnurag S. Maskey #include <libnwam.h>
396ba597c5SAnurag S. Maskey #include "conditions.h"
406ba597c5SAnurag S. Maskey #include "ncu.h"
416ba597c5SAnurag S. Maskey #include "objects.h"
426ba597c5SAnurag S. Maskey #include "util.h"
436ba597c5SAnurag S. Maskey 
446ba597c5SAnurag S. Maskey /*
456ba597c5SAnurag S. Maskey  * conditions.c - contains routines which check state to see if activation
466ba597c5SAnurag S. Maskey  * conditions for NWAM objects are satisfied and rates activation conditions to
476ba597c5SAnurag S. Maskey  * help determine which is most specific.
486ba597c5SAnurag S. Maskey  *
496ba597c5SAnurag S. Maskey  * If the activation-mode is CONDITIONAL_ANY or CONDITIONAL_ALL, the conditions
506ba597c5SAnurag S. Maskey  * property is set to a string made up of conditional expressions. Each
516ba597c5SAnurag S. Maskey  * expression is made up of a condition that can be assigned a boolean value,
526ba597c5SAnurag S. Maskey  * e.g. "system-domain is sun.com" or "ncu ip:bge0 is-not active". If the
536ba597c5SAnurag S. Maskey  * activation-mode is CONDITIONAL_ANY, the condition will be satisfied if any
546ba597c5SAnurag S. Maskey  * one of the conditions is true; if the activation-mode is CONDITIONAL_ALL,
556ba597c5SAnurag S. Maskey  * the condition is satisfied only if all of the conditions are true.
566ba597c5SAnurag S. Maskey  */
576ba597c5SAnurag S. Maskey 
586ba597c5SAnurag S. Maskey uint64_t condition_check_interval = CONDITION_CHECK_INTERVAL_DEFAULT;
596ba597c5SAnurag S. Maskey 
606ba597c5SAnurag S. Maskey extern int getdomainname(char *, int);
616ba597c5SAnurag S. Maskey 
626ba597c5SAnurag S. Maskey /* NCP, NCU, ENM and location conditions */
636ba597c5SAnurag S. Maskey static boolean_t test_condition_ncp(nwam_condition_t condition,
646ba597c5SAnurag S. Maskey     const char *ncp_name);
656ba597c5SAnurag S. Maskey static boolean_t test_condition_ncu(nwam_condition_t condition,
666ba597c5SAnurag S. Maskey     const char *ncu_name);
676ba597c5SAnurag S. Maskey static boolean_t test_condition_enm(nwam_condition_t condition,
686ba597c5SAnurag S. Maskey     const char *enm_name);
696ba597c5SAnurag S. Maskey static boolean_t test_condition_loc(nwam_condition_t condition,
706ba597c5SAnurag S. Maskey     const char *loc_name);
716ba597c5SAnurag S. Maskey 
726ba597c5SAnurag S. Maskey /* IP address conditions */
736ba597c5SAnurag S. Maskey static boolean_t test_condition_ip_address(nwam_condition_t condition,
746ba597c5SAnurag S. Maskey     const char *ip_address);
756ba597c5SAnurag S. Maskey 
766ba597c5SAnurag S. Maskey /* domainname conditions */
776ba597c5SAnurag S. Maskey static boolean_t test_condition_sys_domain(nwam_condition_t condition,
786ba597c5SAnurag S. Maskey     const char *domainname);
796ba597c5SAnurag S. Maskey static boolean_t test_condition_adv_domain(nwam_condition_t condition,
806ba597c5SAnurag S. Maskey     const char *domainname);
816ba597c5SAnurag S. Maskey 
826ba597c5SAnurag S. Maskey /*  WLAN conditions */
836ba597c5SAnurag S. Maskey static boolean_t test_condition_wireless_essid(nwam_condition_t condition,
846ba597c5SAnurag S. Maskey     const char *essid);
856ba597c5SAnurag S. Maskey static boolean_t test_condition_wireless_bssid(nwam_condition_t condition,
866ba597c5SAnurag S. Maskey     const char *essid);
876ba597c5SAnurag S. Maskey 
886ba597c5SAnurag S. Maskey struct nwamd_condition_map {
896ba597c5SAnurag S. Maskey 	nwam_condition_object_type_t object_type;
906ba597c5SAnurag S. Maskey 	boolean_t (*condition_func)(nwam_condition_t, const char *);
916ba597c5SAnurag S. Maskey } condition_map[] =
926ba597c5SAnurag S. Maskey {
936ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_NCP, test_condition_ncp },
946ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_NCU, test_condition_ncu },
956ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_ENM, test_condition_enm },
966ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_LOC, test_condition_loc },
976ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_IP_ADDRESS, test_condition_ip_address },
986ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_SYS_DOMAIN, test_condition_sys_domain },
996ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_ADV_DOMAIN, test_condition_adv_domain },
1006ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_ESSID, test_condition_wireless_essid },
1016ba597c5SAnurag S. Maskey 	{ NWAM_CONDITION_OBJECT_TYPE_BSSID, test_condition_wireless_bssid }
1026ba597c5SAnurag S. Maskey };
1036ba597c5SAnurag S. Maskey 
1046ba597c5SAnurag S. Maskey /*
1056ba597c5SAnurag S. Maskey  * This function takes which kind of conditions (is or is not) we are testing
1066ba597c5SAnurag S. Maskey  * the object against and an object and applies the conditon to the object.
1076ba597c5SAnurag S. Maskey  */
1086ba597c5SAnurag S. Maskey static boolean_t
1096ba597c5SAnurag S. Maskey test_condition_object_state(nwam_condition_t condition,
1106ba597c5SAnurag S. Maskey     nwam_object_type_t object_type, const char *object_name)
1116ba597c5SAnurag S. Maskey {
1126ba597c5SAnurag S. Maskey 	nwamd_object_t object;
1136ba597c5SAnurag S. Maskey 	nwam_state_t state;
1146ba597c5SAnurag S. Maskey 
1156ba597c5SAnurag S. Maskey 	object = nwamd_object_find(object_type, object_name);
1166ba597c5SAnurag S. Maskey 	if (object == NULL)
1176ba597c5SAnurag S. Maskey 		return (B_FALSE);
1186ba597c5SAnurag S. Maskey 
1196ba597c5SAnurag S. Maskey 	state = object->nwamd_object_state;
1206ba597c5SAnurag S. Maskey 	nwamd_object_release(object);
1216ba597c5SAnurag S. Maskey 
1226ba597c5SAnurag S. Maskey 	switch (condition) {
1236ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS:
1246ba597c5SAnurag S. Maskey 		return (state == NWAM_STATE_ONLINE);
1256ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_NOT:
1266ba597c5SAnurag S. Maskey 		return (state != NWAM_STATE_ONLINE);
1276ba597c5SAnurag S. Maskey 	default:
1286ba597c5SAnurag S. Maskey 		return (B_FALSE);
1296ba597c5SAnurag S. Maskey 	}
1306ba597c5SAnurag S. Maskey }
1316ba597c5SAnurag S. Maskey 
1326ba597c5SAnurag S. Maskey static boolean_t
1336ba597c5SAnurag S. Maskey test_condition_ncp(nwam_condition_t condition, const char *name)
1346ba597c5SAnurag S. Maskey {
1356ba597c5SAnurag S. Maskey 	boolean_t active;
1366ba597c5SAnurag S. Maskey 
1376ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&active_ncp_mutex);
1386ba597c5SAnurag S. Maskey 	active = (strcasecmp(active_ncp, name) == 0);
1396ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&active_ncp_mutex);
1406ba597c5SAnurag S. Maskey 
1416ba597c5SAnurag S. Maskey 	switch (condition) {
1426ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS:
1436ba597c5SAnurag S. Maskey 		return (active);
1446ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_NOT:
1456ba597c5SAnurag S. Maskey 		return (active != B_TRUE);
1466ba597c5SAnurag S. Maskey 	default:
1476ba597c5SAnurag S. Maskey 		return (B_FALSE);
1486ba597c5SAnurag S. Maskey 	}
1496ba597c5SAnurag S. Maskey }
1506ba597c5SAnurag S. Maskey 
1516ba597c5SAnurag S. Maskey static boolean_t
1526ba597c5SAnurag S. Maskey test_condition_ncu(nwam_condition_t condition, const char *name)
1536ba597c5SAnurag S. Maskey {
1546ba597c5SAnurag S. Maskey 	char *real_name, *ncu_name;
1556ba597c5SAnurag S. Maskey 	nwam_ncu_handle_t ncuh;
1566ba597c5SAnurag S. Maskey 	nwam_ncu_type_t ncu_type;
1576ba597c5SAnurag S. Maskey 	boolean_t rv;
1586ba597c5SAnurag S. Maskey 
1596ba597c5SAnurag S. Maskey 	/* names are case-insensitive, so get real name from libnwam */
1606ba597c5SAnurag S. Maskey 	if (nwam_ncu_read(active_ncph, name, NWAM_NCU_TYPE_INTERFACE, 0, &ncuh)
1616ba597c5SAnurag S. Maskey 	    == NWAM_SUCCESS) {
1626ba597c5SAnurag S. Maskey 		ncu_type = NWAM_NCU_TYPE_INTERFACE;
1636ba597c5SAnurag S. Maskey 	} else if (nwam_ncu_read(active_ncph, name, NWAM_NCU_TYPE_LINK, 0,
1646ba597c5SAnurag S. Maskey 	    &ncuh) == NWAM_SUCCESS) {
1656ba597c5SAnurag S. Maskey 		ncu_type = NWAM_NCU_TYPE_LINK;
1666ba597c5SAnurag S. Maskey 	} else {
1676ba597c5SAnurag S. Maskey 		return (B_FALSE);
1686ba597c5SAnurag S. Maskey 	}
1696ba597c5SAnurag S. Maskey 	if (nwam_ncu_get_name(ncuh, &real_name) != NWAM_SUCCESS) {
1706ba597c5SAnurag S. Maskey 		nwam_ncu_free(ncuh);
1716ba597c5SAnurag S. Maskey 		return (B_FALSE);
1726ba597c5SAnurag S. Maskey 	}
1736ba597c5SAnurag S. Maskey 	nwam_ncu_free(ncuh);
1746ba597c5SAnurag S. Maskey 
1756ba597c5SAnurag S. Maskey 	/*
1766ba597c5SAnurag S. Maskey 	 * Name may be either unqualified or qualified by NCU type
1776ba597c5SAnurag S. Maskey 	 * (interface:/link:).  Need to translate unqualified names
1786ba597c5SAnurag S. Maskey 	 * to qualified, specifying interface:name if an interface
1796ba597c5SAnurag S. Maskey 	 * NCU is present, otherwise link:ncu.
1806ba597c5SAnurag S. Maskey 	 */
1816ba597c5SAnurag S. Maskey 	if (nwam_ncu_name_to_typed_name(real_name, ncu_type, &ncu_name)
1826ba597c5SAnurag S. Maskey 	    != NWAM_SUCCESS) {
1836ba597c5SAnurag S. Maskey 		free(real_name);
1846ba597c5SAnurag S. Maskey 		return (B_FALSE);
1856ba597c5SAnurag S. Maskey 	}
1866ba597c5SAnurag S. Maskey 	free(real_name);
1876ba597c5SAnurag S. Maskey 
1886ba597c5SAnurag S. Maskey 	rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_NCU,
1896ba597c5SAnurag S. Maskey 	    ncu_name);
1906ba597c5SAnurag S. Maskey 	free(ncu_name);
1916ba597c5SAnurag S. Maskey 	return (rv);
1926ba597c5SAnurag S. Maskey }
1936ba597c5SAnurag S. Maskey 
1946ba597c5SAnurag S. Maskey static boolean_t
1956ba597c5SAnurag S. Maskey test_condition_enm(nwam_condition_t condition, const char *enm_name)
1966ba597c5SAnurag S. Maskey {
1976ba597c5SAnurag S. Maskey 	nwam_enm_handle_t enmh;
1986ba597c5SAnurag S. Maskey 	char *real_name;
1996ba597c5SAnurag S. Maskey 	boolean_t rv;
2006ba597c5SAnurag S. Maskey 
2016ba597c5SAnurag S. Maskey 	/* names are case-insensitive, so get real name from libnwam */
2026ba597c5SAnurag S. Maskey 	if (nwam_enm_read(enm_name, 0, &enmh) != NWAM_SUCCESS)
2036ba597c5SAnurag S. Maskey 		return (B_FALSE);
2046ba597c5SAnurag S. Maskey 	if (nwam_enm_get_name(enmh, &real_name) != NWAM_SUCCESS) {
2056ba597c5SAnurag S. Maskey 		nwam_enm_free(enmh);
2066ba597c5SAnurag S. Maskey 		return (B_FALSE);
2076ba597c5SAnurag S. Maskey 	}
2086ba597c5SAnurag S. Maskey 	nwam_enm_free(enmh);
2096ba597c5SAnurag S. Maskey 
2106ba597c5SAnurag S. Maskey 	rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_ENM,
2116ba597c5SAnurag S. Maskey 	    real_name);
2126ba597c5SAnurag S. Maskey 	free(real_name);
2136ba597c5SAnurag S. Maskey 	return (rv);
2146ba597c5SAnurag S. Maskey }
2156ba597c5SAnurag S. Maskey 
2166ba597c5SAnurag S. Maskey static boolean_t
2176ba597c5SAnurag S. Maskey test_condition_loc(nwam_condition_t condition, const char *loc_name)
2186ba597c5SAnurag S. Maskey {
2196ba597c5SAnurag S. Maskey 	nwam_loc_handle_t loch;
2206ba597c5SAnurag S. Maskey 	char *real_name;
2216ba597c5SAnurag S. Maskey 	boolean_t rv;
2226ba597c5SAnurag S. Maskey 
2236ba597c5SAnurag S. Maskey 	/* names are case-insensitive, so get real name from libnwam */
2246ba597c5SAnurag S. Maskey 	if (nwam_loc_read(loc_name, 0, &loch) != NWAM_SUCCESS)
2256ba597c5SAnurag S. Maskey 		return (B_FALSE);
2266ba597c5SAnurag S. Maskey 	if (nwam_loc_get_name(loch, &real_name) != NWAM_SUCCESS) {
2276ba597c5SAnurag S. Maskey 		nwam_loc_free(loch);
2286ba597c5SAnurag S. Maskey 		return (B_FALSE);
2296ba597c5SAnurag S. Maskey 	}
2306ba597c5SAnurag S. Maskey 	nwam_loc_free(loch);
2316ba597c5SAnurag S. Maskey 
2326ba597c5SAnurag S. Maskey 	rv = test_condition_object_state(condition, NWAM_OBJECT_TYPE_LOC,
2336ba597c5SAnurag S. Maskey 	    real_name);
2346ba597c5SAnurag S. Maskey 	free(real_name);
2356ba597c5SAnurag S. Maskey 	return (rv);
2366ba597c5SAnurag S. Maskey }
2376ba597c5SAnurag S. Maskey 
2386ba597c5SAnurag S. Maskey static boolean_t
2396ba597c5SAnurag S. Maskey test_condition_domain(nwam_condition_t condition, const char *target_domain,
2406ba597c5SAnurag S. Maskey     const char *found_domain)
2416ba597c5SAnurag S. Maskey {
2426ba597c5SAnurag S. Maskey 	int i, len_t, len_f;
2436ba597c5SAnurag S. Maskey 	char target[MAXHOSTNAMELEN], found[MAXHOSTNAMELEN];
2446ba597c5SAnurag S. Maskey 
2456ba597c5SAnurag S. Maskey 	len_t = target_domain == NULL ? 0 : strlen(target_domain);
2466ba597c5SAnurag S. Maskey 	len_f = found_domain == NULL ? 0 : strlen(found_domain);
2476ba597c5SAnurag S. Maskey 
2486ba597c5SAnurag S. Maskey 	/* convert target_domain and found_domain to lowercase for strstr() */
2496ba597c5SAnurag S. Maskey 	for (i = 0; i < len_t; i++)
2506ba597c5SAnurag S. Maskey 		target[i] = tolower(target_domain[i]);
2516ba597c5SAnurag S. Maskey 	target[len_t] = '\0';
2526ba597c5SAnurag S. Maskey 
2536ba597c5SAnurag S. Maskey 	for (i = 0; i < len_f; i++)
2546ba597c5SAnurag S. Maskey 		found[i] = tolower(found_domain[i]);
2556ba597c5SAnurag S. Maskey 	found[len_f] = '\0';
2566ba597c5SAnurag S. Maskey 
2576ba597c5SAnurag S. Maskey 	switch (condition) {
2586ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS:
2596ba597c5SAnurag S. Maskey 		return (found_domain != NULL && strcmp(found, target) == 0);
2606ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_NOT:
2616ba597c5SAnurag S. Maskey 		return (found_domain == NULL || strcmp(found, target) != 0);
2626ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_CONTAINS:
2636ba597c5SAnurag S. Maskey 		return (found_domain != NULL && strstr(found, target) != NULL);
2646ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_DOES_NOT_CONTAIN:
2656ba597c5SAnurag S. Maskey 		return (found_domain == NULL || strstr(found, target) == NULL);
2666ba597c5SAnurag S. Maskey 	default:
2676ba597c5SAnurag S. Maskey 		return (B_FALSE);
2686ba597c5SAnurag S. Maskey 	}
2696ba597c5SAnurag S. Maskey }
2706ba597c5SAnurag S. Maskey 
2716ba597c5SAnurag S. Maskey struct ncu_adv_domains {
2726ba597c5SAnurag S. Maskey 	struct ncu_adv_domains *next;
2736ba597c5SAnurag S. Maskey 	char *dns_domain;
2746ba597c5SAnurag S. Maskey 	char *nis_domain;
2756ba597c5SAnurag S. Maskey };
2766ba597c5SAnurag S. Maskey 
2776ba597c5SAnurag S. Maskey static int
2786ba597c5SAnurag S. Maskey get_adv_domains(nwamd_object_t obj, void *arg)
2796ba597c5SAnurag S. Maskey {
2806ba597c5SAnurag S. Maskey 	nwamd_ncu_t *ncu = (nwamd_ncu_t *)obj->nwamd_object_data;
2816ba597c5SAnurag S. Maskey 	struct ncu_adv_domains **headpp = (struct ncu_adv_domains **)arg;
2826ba597c5SAnurag S. Maskey 	struct ncu_adv_domains *adp;
2836ba597c5SAnurag S. Maskey 	char *dns, *nis;
2846ba597c5SAnurag S. Maskey 
2856ba597c5SAnurag S. Maskey 	if (ncu->ncu_type != NWAM_NCU_TYPE_INTERFACE)
2866ba597c5SAnurag S. Maskey 		return (0);
2876ba597c5SAnurag S. Maskey 
2886ba597c5SAnurag S. Maskey 	dns = nwamd_get_dhcpinfo_data("DNSdmain", ncu->ncu_name);
2896ba597c5SAnurag S. Maskey 	nis = nwamd_get_dhcpinfo_data("NISdmain", ncu->ncu_name);
2906ba597c5SAnurag S. Maskey 
2916ba597c5SAnurag S. Maskey 	if (dns != NULL || nis != NULL) {
2926ba597c5SAnurag S. Maskey 		adp = (struct ncu_adv_domains *)malloc(sizeof (*adp));
2936ba597c5SAnurag S. Maskey 		if (adp == NULL)
2946ba597c5SAnurag S. Maskey 			return (1);
2956ba597c5SAnurag S. Maskey 		adp->dns_domain = dns;
2966ba597c5SAnurag S. Maskey 		adp->nis_domain = nis;
2976ba597c5SAnurag S. Maskey 		adp->next = *headpp;
2986ba597c5SAnurag S. Maskey 		*headpp = adp;
2996ba597c5SAnurag S. Maskey 	}
3006ba597c5SAnurag S. Maskey 
3016ba597c5SAnurag S. Maskey 	return (0);
3026ba597c5SAnurag S. Maskey }
3036ba597c5SAnurag S. Maskey 
3046ba597c5SAnurag S. Maskey static boolean_t
3056ba597c5SAnurag S. Maskey test_condition_sys_domain(nwam_condition_t condition, const char *domainname)
3066ba597c5SAnurag S. Maskey {
3076ba597c5SAnurag S. Maskey 	char cur_domainname[MAXHOSTNAMELEN];
3086ba597c5SAnurag S. Maskey 
3096ba597c5SAnurag S. Maskey 	if (getdomainname(cur_domainname, MAXHOSTNAMELEN) != 0)
3106ba597c5SAnurag S. Maskey 		return (B_FALSE);
3116ba597c5SAnurag S. Maskey 
3126ba597c5SAnurag S. Maskey 	return (test_condition_domain(condition, domainname, cur_domainname));
3136ba597c5SAnurag S. Maskey }
3146ba597c5SAnurag S. Maskey 
3156ba597c5SAnurag S. Maskey static boolean_t
3166ba597c5SAnurag S. Maskey test_condition_adv_domain(nwam_condition_t condition, const char *domainname)
3176ba597c5SAnurag S. Maskey {
3186ba597c5SAnurag S. Maskey 	struct ncu_adv_domains *adv_domains = NULL;
3196ba597c5SAnurag S. Maskey 	struct ncu_adv_domains *adp, *prev;
3206ba597c5SAnurag S. Maskey 	boolean_t positive, rtn;
3216ba597c5SAnurag S. Maskey 
3226ba597c5SAnurag S. Maskey 	(void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, get_adv_domains,
3236ba597c5SAnurag S. Maskey 	    &adv_domains);
3246ba597c5SAnurag S. Maskey 
3256ba597c5SAnurag S. Maskey 	positive = (condition == NWAM_CONDITION_IS ||
3266ba597c5SAnurag S. Maskey 	    condition == NWAM_CONDITION_CONTAINS);
3276ba597c5SAnurag S. Maskey 
3286ba597c5SAnurag S. Maskey 	/*
3296ba597c5SAnurag S. Maskey 	 * Walk the advertised domain list.  Our test function tests one
3306ba597c5SAnurag S. Maskey 	 * single domain, but we're dealing with a list: if our condition
3316ba597c5SAnurag S. Maskey 	 * is positive ('is' or 'contains'), the test function for each
3326ba597c5SAnurag S. Maskey 	 * domain results are or'd together; if our condition is negative
3336ba597c5SAnurag S. Maskey 	 * ('is-not' or 'does-not-contain'), the test function results must
3346ba597c5SAnurag S. Maskey 	 * be and'd.  Thus our short-circuit exit value depends on our
3356ba597c5SAnurag S. Maskey 	 * condition: if the test function returns TRUE it implies immediate
3366ba597c5SAnurag S. Maskey 	 * success for a positive condition; if it returns FALSE it implies
3376ba597c5SAnurag S. Maskey 	 * immediate failure for a negative condition.
3386ba597c5SAnurag S. Maskey 	 */
3396ba597c5SAnurag S. Maskey 	adp = adv_domains;
3406ba597c5SAnurag S. Maskey 	while (adp != NULL) {
3416ba597c5SAnurag S. Maskey 		if ((test_condition_domain(condition, domainname,
3426ba597c5SAnurag S. Maskey 		    adp->dns_domain) == positive) ||
3436ba597c5SAnurag S. Maskey 		    (test_condition_domain(condition, domainname,
3446ba597c5SAnurag S. Maskey 		    adp->nis_domain) == positive)) {
3456ba597c5SAnurag S. Maskey 			rtn = positive;
3466ba597c5SAnurag S. Maskey 			break;
3476ba597c5SAnurag S. Maskey 		}
3486ba597c5SAnurag S. Maskey 		adp = adp->next;
3496ba597c5SAnurag S. Maskey 	}
3506ba597c5SAnurag S. Maskey 	if (adp == NULL) {
3516ba597c5SAnurag S. Maskey 		/*
3526ba597c5SAnurag S. Maskey 		 * We did not short-circuit; we therefore failed if our
3536ba597c5SAnurag S. Maskey 		 * condition was positive, and succeeded if our condition
3546ba597c5SAnurag S. Maskey 		 * was negative.
3556ba597c5SAnurag S. Maskey 		 */
3566ba597c5SAnurag S. Maskey 		rtn = !positive;
3576ba597c5SAnurag S. Maskey 	}
3586ba597c5SAnurag S. Maskey 
3596ba597c5SAnurag S. Maskey 	/* now free the domain list */
3606ba597c5SAnurag S. Maskey 	adp = adv_domains;
3616ba597c5SAnurag S. Maskey 	while (adp != NULL) {
3626ba597c5SAnurag S. Maskey 		prev = adp;
3636ba597c5SAnurag S. Maskey 		adp = prev->next;
3646ba597c5SAnurag S. Maskey 		free(prev->dns_domain);
3656ba597c5SAnurag S. Maskey 		free(prev->nis_domain);
3666ba597c5SAnurag S. Maskey 		free(prev);
3676ba597c5SAnurag S. Maskey 	}
3686ba597c5SAnurag S. Maskey 
3696ba597c5SAnurag S. Maskey 	return (rtn);
3706ba597c5SAnurag S. Maskey }
3716ba597c5SAnurag S. Maskey 
3726ba597c5SAnurag S. Maskey /*
3736ba597c5SAnurag S. Maskey  * Returns true if prefixlen bits of addr1 match prefixlen bits of addr2.
3746ba597c5SAnurag S. Maskey  */
3756ba597c5SAnurag S. Maskey static boolean_t
3766ba597c5SAnurag S. Maskey prefixmatch(uchar_t *addr1, uchar_t *addr2, int prefixlen)
3776ba597c5SAnurag S. Maskey {
3786ba597c5SAnurag S. Maskey 	uchar_t mask[IPV6_ABITS/8];
3796ba597c5SAnurag S. Maskey 	int i, j = 0;
3806ba597c5SAnurag S. Maskey 
3816ba597c5SAnurag S. Maskey 	if (prefixlen == 0)
3826ba597c5SAnurag S. Maskey 		return (B_TRUE);
3836ba597c5SAnurag S. Maskey 
3846ba597c5SAnurag S. Maskey 	while (prefixlen > 0) {
3856ba597c5SAnurag S. Maskey 		if (prefixlen >= 8) {
3866ba597c5SAnurag S. Maskey 			mask[j++] = 0xFF;
3876ba597c5SAnurag S. Maskey 			prefixlen -= 8;
3886ba597c5SAnurag S. Maskey 		} else {
3896ba597c5SAnurag S. Maskey 			mask[j] |= 1 << (8 - prefixlen);
3906ba597c5SAnurag S. Maskey 			prefixlen--;
3916ba597c5SAnurag S. Maskey 		}
3926ba597c5SAnurag S. Maskey 	}
3936ba597c5SAnurag S. Maskey 	/* Ensure at least one byte is tested */
3946ba597c5SAnurag S. Maskey 	if (j == 0) j++;
3956ba597c5SAnurag S. Maskey 
3966ba597c5SAnurag S. Maskey 	for (i = 0; i < j; i++) {
3976ba597c5SAnurag S. Maskey 		if ((addr1[i] & mask[i]) != (addr2[i] & mask[i]))
3986ba597c5SAnurag S. Maskey 			return (B_FALSE);
3996ba597c5SAnurag S. Maskey 	}
4006ba597c5SAnurag S. Maskey 	return (B_TRUE);
4016ba597c5SAnurag S. Maskey }
4026ba597c5SAnurag S. Maskey 
403*f6da83d4SAnurag S. Maskey /*
404*f6da83d4SAnurag S. Maskey  * Given a string representation of an IPv4 or IPv6 address returns the
405*f6da83d4SAnurag S. Maskey  * sockaddr representation. Note that 'sockaddr' should point at the correct
406*f6da83d4SAnurag S. Maskey  * sockaddr structure for the address family (sockaddr_in for AF_INET or
407*f6da83d4SAnurag S. Maskey  * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
408*f6da83d4SAnurag S. Maskey  * structure.
409*f6da83d4SAnurag S. Maskey  */
410*f6da83d4SAnurag S. Maskey static struct sockaddr_storage *
411*f6da83d4SAnurag S. Maskey nwamd_str2sockaddr(sa_family_t af, const char *straddr,
412*f6da83d4SAnurag S. Maskey     struct sockaddr_storage *addr)
413*f6da83d4SAnurag S. Maskey {
414*f6da83d4SAnurag S. Maskey 	struct sockaddr_in *sin;
415*f6da83d4SAnurag S. Maskey 	struct sockaddr_in6 *sin6;
416*f6da83d4SAnurag S. Maskey 	int err;
417*f6da83d4SAnurag S. Maskey 
418*f6da83d4SAnurag S. Maskey 	if (af == AF_INET) {
419*f6da83d4SAnurag S. Maskey 		sin = (struct sockaddr_in *)addr;
420*f6da83d4SAnurag S. Maskey 		sin->sin_family = AF_INET;
421*f6da83d4SAnurag S. Maskey 		err = inet_pton(AF_INET, straddr, &sin->sin_addr);
422*f6da83d4SAnurag S. Maskey 	} else if (af == AF_INET6) {
423*f6da83d4SAnurag S. Maskey 		sin6 = (struct sockaddr_in6 *)addr;
424*f6da83d4SAnurag S. Maskey 		sin6->sin6_family = AF_INET6;
425*f6da83d4SAnurag S. Maskey 		err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr);
426*f6da83d4SAnurag S. Maskey 	} else {
427*f6da83d4SAnurag S. Maskey 		errno = EINVAL;
428*f6da83d4SAnurag S. Maskey 		return (NULL);
429*f6da83d4SAnurag S. Maskey 	}
430*f6da83d4SAnurag S. Maskey 	return (err == 1 ? addr : NULL);
431*f6da83d4SAnurag S. Maskey }
432*f6da83d4SAnurag S. Maskey 
4336ba597c5SAnurag S. Maskey struct nwamd_ipaddr_condition_walk_arg {
4346ba597c5SAnurag S. Maskey 	nwam_condition_t condition;
4356ba597c5SAnurag S. Maskey 	struct sockaddr_storage sockaddr;
4366ba597c5SAnurag S. Maskey 	int prefixlen;
4376ba597c5SAnurag S. Maskey 	boolean_t res;
4386ba597c5SAnurag S. Maskey };
4396ba597c5SAnurag S. Maskey 
4406ba597c5SAnurag S. Maskey static int
441*f6da83d4SAnurag S. Maskey check_ipaddr(sa_family_t family, struct ifaddrs *ifa, void *arg)
4426ba597c5SAnurag S. Maskey {
4436ba597c5SAnurag S. Maskey 	struct nwamd_ipaddr_condition_walk_arg *wa = arg;
4446ba597c5SAnurag S. Maskey 	boolean_t match = B_FALSE;
4456ba597c5SAnurag S. Maskey 	uchar_t *addr1, *addr2;
4466ba597c5SAnurag S. Maskey 
447*f6da83d4SAnurag S. Maskey 	if (family == AF_INET) {
4486ba597c5SAnurag S. Maskey 		addr1 = (uchar_t *)&(((struct sockaddr_in *)
449*f6da83d4SAnurag S. Maskey 		    ifa->ifa_addr)->sin_addr.s_addr);
4506ba597c5SAnurag S. Maskey 		addr2 = (uchar_t *)&(((struct sockaddr_in *)
4516ba597c5SAnurag S. Maskey 		    &(wa->sockaddr))->sin_addr.s_addr);
4526ba597c5SAnurag S. Maskey 	} else {
4536ba597c5SAnurag S. Maskey 		addr1 = (uchar_t *)&(((struct sockaddr_in6 *)
454*f6da83d4SAnurag S. Maskey 		    ifa->ifa_addr)->sin6_addr.s6_addr);
4556ba597c5SAnurag S. Maskey 		addr2 = (uchar_t *)&(((struct sockaddr_in6 *)
4566ba597c5SAnurag S. Maskey 		    &(wa->sockaddr))->sin6_addr.s6_addr);
4576ba597c5SAnurag S. Maskey 	}
4586ba597c5SAnurag S. Maskey 
4596ba597c5SAnurag S. Maskey 	match = prefixmatch(addr1, addr2, wa->prefixlen);
4606ba597c5SAnurag S. Maskey 
4616ba597c5SAnurag S. Maskey 	nlog(LOG_DEBUG, "check_ipaddr: match %d\n", match);
4626ba597c5SAnurag S. Maskey 	switch (wa->condition) {
4636ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS:
4646ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_IN_RANGE:
4656ba597c5SAnurag S. Maskey 		wa->res = match;
4666ba597c5SAnurag S. Maskey 		if (match)
4676ba597c5SAnurag S. Maskey 			return (1);
4686ba597c5SAnurag S. Maskey 		return (0);
4696ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_NOT:
4706ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_NOT_IN_RANGE:
4716ba597c5SAnurag S. Maskey 		wa->res = !match;
4726ba597c5SAnurag S. Maskey 		return (0);
4736ba597c5SAnurag S. Maskey 	default:
4746ba597c5SAnurag S. Maskey 		return (0);
4756ba597c5SAnurag S. Maskey 	}
4766ba597c5SAnurag S. Maskey }
4776ba597c5SAnurag S. Maskey 
4786ba597c5SAnurag S. Maskey static boolean_t
4796ba597c5SAnurag S. Maskey test_condition_ip_address(nwam_condition_t condition,
4806ba597c5SAnurag S. Maskey     const char *ip_address_string)
4816ba597c5SAnurag S. Maskey {
482*f6da83d4SAnurag S. Maskey 	sa_family_t family;
4836ba597c5SAnurag S. Maskey 	char *copy, *ip_address, *prefixlen_string, *lasts;
4846ba597c5SAnurag S. Maskey 	struct nwamd_ipaddr_condition_walk_arg wa;
485*f6da83d4SAnurag S. Maskey 	struct ifaddrs *ifap, *ifa;
4866ba597c5SAnurag S. Maskey 
4876ba597c5SAnurag S. Maskey 	if ((copy = strdup(ip_address_string)) == NULL)
4886ba597c5SAnurag S. Maskey 		return (B_FALSE);
4896ba597c5SAnurag S. Maskey 
4906ba597c5SAnurag S. Maskey 	if ((ip_address = strtok_r(copy, " \t/", &lasts)) == NULL) {
4916ba597c5SAnurag S. Maskey 		free(copy);
4926ba597c5SAnurag S. Maskey 		return (B_FALSE);
4936ba597c5SAnurag S. Maskey 	}
4946ba597c5SAnurag S. Maskey 
4956ba597c5SAnurag S. Maskey 	prefixlen_string = strtok_r(NULL, " \t", &lasts);
4966ba597c5SAnurag S. Maskey 
497*f6da83d4SAnurag S. Maskey 	if (nwamd_str2sockaddr(AF_INET, ip_address, &wa.sockaddr) != NULL) {
498*f6da83d4SAnurag S. Maskey 		family = AF_INET;
4996ba597c5SAnurag S. Maskey 		wa.prefixlen = IP_ABITS;
500*f6da83d4SAnurag S. Maskey 	} else if (nwamd_str2sockaddr(AF_INET6, ip_address, &wa.sockaddr)
501*f6da83d4SAnurag S. Maskey 	    != NULL) {
502*f6da83d4SAnurag S. Maskey 		family = AF_INET6;
5036ba597c5SAnurag S. Maskey 		wa.prefixlen = IPV6_ABITS;
5046ba597c5SAnurag S. Maskey 	} else {
5056ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "test_condition_ip_address: "
506*f6da83d4SAnurag S. Maskey 		    "nwamd_str2sockaddr failed for %s: %s", ip_address,
507*f6da83d4SAnurag S. Maskey 		    strerror(errno));
5086ba597c5SAnurag S. Maskey 		free(copy);
5096ba597c5SAnurag S. Maskey 		return (B_FALSE);
5106ba597c5SAnurag S. Maskey 	}
5116ba597c5SAnurag S. Maskey 
5126ba597c5SAnurag S. Maskey 	if (prefixlen_string != NULL)
5136ba597c5SAnurag S. Maskey 		wa.prefixlen = atoi(prefixlen_string);
5146ba597c5SAnurag S. Maskey 
5156ba597c5SAnurag S. Maskey 	wa.condition = condition;
5166ba597c5SAnurag S. Maskey 
5176ba597c5SAnurag S. Maskey 	switch (condition) {
5186ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS:
5196ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_IN_RANGE:
5206ba597c5SAnurag S. Maskey 		wa.res = B_FALSE;
5216ba597c5SAnurag S. Maskey 		break;
5226ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_NOT:
5236ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS_NOT_IN_RANGE:
5246ba597c5SAnurag S. Maskey 		wa.res = B_TRUE;
5256ba597c5SAnurag S. Maskey 		break;
5266ba597c5SAnurag S. Maskey 	default:
5276ba597c5SAnurag S. Maskey 		free(copy);
5286ba597c5SAnurag S. Maskey 		return (B_FALSE);
5296ba597c5SAnurag S. Maskey 	}
5306ba597c5SAnurag S. Maskey 	free(copy);
5316ba597c5SAnurag S. Maskey 
532*f6da83d4SAnurag S. Maskey 	if (getifaddrs(&ifa) == -1) {
533*f6da83d4SAnurag S. Maskey 		nlog(LOG_ERR, "test_condition_ip_address: "
534*f6da83d4SAnurag S. Maskey 		    "getifaddrs failed: %s", strerror(errno));
535*f6da83d4SAnurag S. Maskey 		return (wa.res);
536*f6da83d4SAnurag S. Maskey 	}
537*f6da83d4SAnurag S. Maskey 	for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
538*f6da83d4SAnurag S. Maskey 		if (ifap->ifa_addr->ss_family != family)
539*f6da83d4SAnurag S. Maskey 			continue;
540*f6da83d4SAnurag S. Maskey 		if (check_ipaddr(family, ifap, &wa) == 1)
541*f6da83d4SAnurag S. Maskey 			break;
542*f6da83d4SAnurag S. Maskey 	}
543*f6da83d4SAnurag S. Maskey 	freeifaddrs(ifa);
544*f6da83d4SAnurag S. Maskey 
5456ba597c5SAnurag S. Maskey 	return (wa.res);
5466ba597c5SAnurag S. Maskey }
5476ba597c5SAnurag S. Maskey 
5486ba597c5SAnurag S. Maskey struct nwamd_wlan_condition_walk_arg {
5496ba597c5SAnurag S. Maskey 	nwam_condition_t condition;
5506ba597c5SAnurag S. Maskey 	const char *exp_essid;
5516ba597c5SAnurag S. Maskey 	const char *exp_bssid;
5526ba597c5SAnurag S. Maskey 	uint_t num_connected;
5536ba597c5SAnurag S. Maskey 	boolean_t res;
5546ba597c5SAnurag S. Maskey };
5556ba597c5SAnurag S. Maskey 
5566ba597c5SAnurag S. Maskey static int
5576ba597c5SAnurag S. Maskey check_wlan(const char *linkname, void *arg)
5586ba597c5SAnurag S. Maskey {
5596ba597c5SAnurag S. Maskey 	struct nwamd_wlan_condition_walk_arg *wa = arg;
5606ba597c5SAnurag S. Maskey 	datalink_id_t linkid;
5616ba597c5SAnurag S. Maskey 	dladm_wlan_linkattr_t attr;
5626ba597c5SAnurag S. Maskey 	dladm_status_t status;
5636ba597c5SAnurag S. Maskey 	char cur_essid[DLADM_STRSIZE];
5646ba597c5SAnurag S. Maskey 	char cur_bssid[DLADM_STRSIZE];
5656ba597c5SAnurag S. Maskey 	char errmsg[DLADM_STRSIZE];
5666ba597c5SAnurag S. Maskey 
5676ba597c5SAnurag S. Maskey 	if ((status = dladm_name2info(dld_handle, linkname, &linkid, NULL, NULL,
5686ba597c5SAnurag S. Maskey 	    NULL)) != DLADM_STATUS_OK) {
5696ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "check_wlan: dladm_name2info() for %s "
5706ba597c5SAnurag S. Maskey 		    "failed: %s", linkname,
5716ba597c5SAnurag S. Maskey 		    dladm_status2str(status, errmsg));
5726ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
5736ba597c5SAnurag S. Maskey 	}
5746ba597c5SAnurag S. Maskey 
5756ba597c5SAnurag S. Maskey 	status = dladm_wlan_get_linkattr(dld_handle, linkid, &attr);
5766ba597c5SAnurag S. Maskey 	if (status != DLADM_STATUS_OK) {
5776ba597c5SAnurag S. Maskey 		nlog(LOG_DEBUG, "check_wlan: dladm_wlan_get_linkattr() for %s "
5786ba597c5SAnurag S. Maskey 		    "failed: %s", linkname,
5796ba597c5SAnurag S. Maskey 		    dladm_status2str(status, errmsg));
5806ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
5816ba597c5SAnurag S. Maskey 	}
5826ba597c5SAnurag S. Maskey 	if (attr.la_status == DLADM_WLAN_LINK_DISCONNECTED)
5836ba597c5SAnurag S. Maskey 		return (DLADM_WALK_TERMINATE);
5846ba597c5SAnurag S. Maskey 
5856ba597c5SAnurag S. Maskey 	wa->num_connected++;
5866ba597c5SAnurag S. Maskey 
5876ba597c5SAnurag S. Maskey 	if (wa->exp_essid != NULL) {
5886ba597c5SAnurag S. Maskey 		/* Is the NIC associated with the expected access point? */
5896ba597c5SAnurag S. Maskey 		(void) dladm_wlan_essid2str(&attr.la_wlan_attr.wa_essid,
5906ba597c5SAnurag S. Maskey 		    cur_essid);
5916ba597c5SAnurag S. Maskey 		switch (wa->condition) {
5926ba597c5SAnurag S. Maskey 		case NWAM_CONDITION_IS:
5936ba597c5SAnurag S. Maskey 			wa->res = strcmp(cur_essid, wa->exp_essid) == 0;
5946ba597c5SAnurag S. Maskey 			if (wa->res)
5956ba597c5SAnurag S. Maskey 				return (DLADM_WALK_TERMINATE);
5966ba597c5SAnurag S. Maskey 			break;
5976ba597c5SAnurag S. Maskey 		case NWAM_CONDITION_IS_NOT:
5986ba597c5SAnurag S. Maskey 			wa->res = strcmp(cur_essid, wa->exp_essid) != 0;
5996ba597c5SAnurag S. Maskey 			if (!wa->res)
6006ba597c5SAnurag S. Maskey 				return (DLADM_WALK_TERMINATE);
6016ba597c5SAnurag S. Maskey 			break;
6026ba597c5SAnurag S. Maskey 		case NWAM_CONDITION_CONTAINS:
6036ba597c5SAnurag S. Maskey 			wa->res = strstr(cur_essid, wa->exp_essid) != NULL;
6046ba597c5SAnurag S. Maskey 			if (wa->res)
6056ba597c5SAnurag S. Maskey 				return (DLADM_WALK_TERMINATE);
6066ba597c5SAnurag S. Maskey 			break;
6076ba597c5SAnurag S. Maskey 		case NWAM_CONDITION_DOES_NOT_CONTAIN:
6086ba597c5SAnurag S. Maskey 			wa->res = strstr(cur_essid, wa->exp_essid) == NULL;
6096ba597c5SAnurag S. Maskey 			if (!wa->res)
6106ba597c5SAnurag S. Maskey 				return (DLADM_WALK_TERMINATE);
6116ba597c5SAnurag S. Maskey 			break;
6126ba597c5SAnurag S. Maskey 		default:
6136ba597c5SAnurag S. Maskey 			return (DLADM_WALK_TERMINATE);
6146ba597c5SAnurag S. Maskey 		}
6156ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
6166ba597c5SAnurag S. Maskey 	}
6176ba597c5SAnurag S. Maskey 	if (wa->exp_bssid != NULL) {
6186ba597c5SAnurag S. Maskey 		/* Is the NIC associated with the expected access point? */
6196ba597c5SAnurag S. Maskey 		(void) dladm_wlan_bssid2str(&attr.la_wlan_attr.wa_bssid,
6206ba597c5SAnurag S. Maskey 		    cur_bssid);
6216ba597c5SAnurag S. Maskey 		switch (wa->condition) {
6226ba597c5SAnurag S. Maskey 		case NWAM_CONDITION_IS:
6236ba597c5SAnurag S. Maskey 			wa->res = strcmp(cur_bssid, wa->exp_bssid) == 0;
6246ba597c5SAnurag S. Maskey 			if (wa->res)
6256ba597c5SAnurag S. Maskey 				return (DLADM_WALK_TERMINATE);
6266ba597c5SAnurag S. Maskey 			break;
6276ba597c5SAnurag S. Maskey 		case NWAM_CONDITION_IS_NOT:
6286ba597c5SAnurag S. Maskey 			wa->res = strcmp(cur_bssid, wa->exp_bssid) != 0;
6296ba597c5SAnurag S. Maskey 			if (!wa->res)
6306ba597c5SAnurag S. Maskey 				return (DLADM_WALK_TERMINATE);
6316ba597c5SAnurag S. Maskey 			break;
6326ba597c5SAnurag S. Maskey 		default:
6336ba597c5SAnurag S. Maskey 			return (DLADM_WALK_TERMINATE);
6346ba597c5SAnurag S. Maskey 		}
6356ba597c5SAnurag S. Maskey 		return (DLADM_WALK_CONTINUE);
6366ba597c5SAnurag S. Maskey 	}
6376ba597c5SAnurag S. Maskey 	/*
6386ba597c5SAnurag S. Maskey 	 * Neither an ESSID or BSSID match is required - being connected to a
6396ba597c5SAnurag S. Maskey 	 * WLAN is enough.
6406ba597c5SAnurag S. Maskey 	 */
6416ba597c5SAnurag S. Maskey 	switch (wa->condition) {
6426ba597c5SAnurag S. Maskey 	case NWAM_CONDITION_IS:
6436ba597c5SAnurag S. Maskey 		wa->res = B_TRUE;
6446ba597c5SAnurag S. Maskey 		return (DLADM_WALK_TERMINATE);
6456ba597c5SAnurag S. Maskey 	default:
6466ba597c5SAnurag S. Maskey 		wa->res = B_FALSE;
6476ba597c5SAnurag S. Maskey 		return (DLADM_WALK_TERMINATE);
6486ba597c5SAnurag S. Maskey 	}
6496ba597c5SAnurag S. Maskey 	/*NOTREACHED*/
6506ba597c5SAnurag S. Maskey 	return (DLADM_WALK_CONTINUE);
6516ba597c5SAnurag S. Maskey }
6526ba597c5SAnurag S. Maskey 
6536ba597c5SAnurag S. Maskey static boolean_t
6546ba597c5SAnurag S. Maskey test_condition_wireless_essid(nwam_condition_t condition,
6556ba597c5SAnurag S. Maskey     const char *essid)
6566ba597c5SAnurag S. Maskey {
6576ba597c5SAnurag S. Maskey 	struct nwamd_wlan_condition_walk_arg wa;
6586ba597c5SAnurag S. Maskey 
6596ba597c5SAnurag S. Maskey 	wa.condition = condition;
6606ba597c5SAnurag S. Maskey 	wa.exp_essid = essid;
6616ba597c5SAnurag S. Maskey 	wa.exp_bssid = NULL;
6626ba597c5SAnurag S. Maskey 	wa.num_connected = 0;
6636ba597c5SAnurag S. Maskey 	wa.res = B_FALSE;
6646ba597c5SAnurag S. Maskey 
6656ba597c5SAnurag S. Maskey 	(void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS,
6666ba597c5SAnurag S. Maskey 	    DL_WIFI, DLADM_OPT_ACTIVE);
6676ba597c5SAnurag S. Maskey 
6686ba597c5SAnurag S. Maskey 	return (wa.num_connected > 0 && wa.res == B_TRUE);
6696ba597c5SAnurag S. Maskey }
6706ba597c5SAnurag S. Maskey 
6716ba597c5SAnurag S. Maskey static boolean_t
6726ba597c5SAnurag S. Maskey test_condition_wireless_bssid(nwam_condition_t condition,
6736ba597c5SAnurag S. Maskey     const char *bssid)
6746ba597c5SAnurag S. Maskey {
6756ba597c5SAnurag S. Maskey 	struct nwamd_wlan_condition_walk_arg wa;
6766ba597c5SAnurag S. Maskey 
6776ba597c5SAnurag S. Maskey 	wa.condition = condition;
6786ba597c5SAnurag S. Maskey 	wa.exp_bssid = bssid;
6796ba597c5SAnurag S. Maskey 	wa.exp_essid = NULL;
6806ba597c5SAnurag S. Maskey 	wa.num_connected = 0;
6816ba597c5SAnurag S. Maskey 	wa.res = B_FALSE;
6826ba597c5SAnurag S. Maskey 
6836ba597c5SAnurag S. Maskey 	(void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS,
6846ba597c5SAnurag S. Maskey 	    DL_WIFI, DLADM_OPT_ACTIVE);
6856ba597c5SAnurag S. Maskey 
6866ba597c5SAnurag S. Maskey 	return (wa.num_connected > 0 && wa.res == B_TRUE);
6876ba597c5SAnurag S. Maskey }
6886ba597c5SAnurag S. Maskey 
6896ba597c5SAnurag S. Maskey /*
6906ba597c5SAnurag S. Maskey  * This function takes an activation mode and a string representation of a
6916ba597c5SAnurag S. Maskey  * condition and evaluates it.
6926ba597c5SAnurag S. Maskey  */
6936ba597c5SAnurag S. Maskey boolean_t
6946ba597c5SAnurag S. Maskey nwamd_check_conditions(nwam_activation_mode_t activation_mode,
6956ba597c5SAnurag S. Maskey     char **condition_strings, uint_t num_conditions)
6966ba597c5SAnurag S. Maskey {
6976ba597c5SAnurag S. Maskey 	boolean_t ret;
6986ba597c5SAnurag S. Maskey 	nwam_condition_t condition;
6996ba597c5SAnurag S. Maskey 	nwam_condition_object_type_t object_type;
7006ba597c5SAnurag S. Maskey 	char *object_name;
7016ba597c5SAnurag S. Maskey 	int i, j;
7026ba597c5SAnurag S. Maskey 
7036ba597c5SAnurag S. Maskey 	for (i = 0; i < num_conditions; i++) {
7046ba597c5SAnurag S. Maskey 
7056ba597c5SAnurag S. Maskey 		if (nwam_condition_string_to_condition(condition_strings[i],
7066ba597c5SAnurag S. Maskey 		    &object_type, &condition, &object_name) != NWAM_SUCCESS) {
7076ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "check_conditions: invalid condition %s",
7086ba597c5SAnurag S. Maskey 			    condition_strings[i]);
7096ba597c5SAnurag S. Maskey 			return (B_FALSE);
7106ba597c5SAnurag S. Maskey 		}
7116ba597c5SAnurag S. Maskey 		ret = B_FALSE;
7126ba597c5SAnurag S. Maskey 
7136ba597c5SAnurag S. Maskey 		for (j = 0; j < (sizeof (condition_map) /
7146ba597c5SAnurag S. Maskey 		    sizeof (struct nwamd_condition_map)); j++) {
7156ba597c5SAnurag S. Maskey 			if (condition_map[j].object_type == object_type)
7166ba597c5SAnurag S. Maskey 				ret = condition_map[j].condition_func(condition,
7176ba597c5SAnurag S. Maskey 				    object_name);
7186ba597c5SAnurag S. Maskey 		}
7196ba597c5SAnurag S. Maskey 
7206ba597c5SAnurag S. Maskey 		free(object_name);
7216ba597c5SAnurag S. Maskey 
7226ba597c5SAnurag S. Maskey 		if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY &&
7236ba597c5SAnurag S. Maskey 		    ret) {
7246ba597c5SAnurag S. Maskey 			return (B_TRUE);
7256ba597c5SAnurag S. Maskey 		}
7266ba597c5SAnurag S. Maskey 		if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL &&
7276ba597c5SAnurag S. Maskey 		    !ret) {
7286ba597c5SAnurag S. Maskey 			return (B_FALSE);
7296ba597c5SAnurag S. Maskey 		}
7306ba597c5SAnurag S. Maskey 	}
7316ba597c5SAnurag S. Maskey 	if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY && ret)
7326ba597c5SAnurag S. Maskey 		return (B_TRUE);
7336ba597c5SAnurag S. Maskey 	if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL && ret)
7346ba597c5SAnurag S. Maskey 		return (B_TRUE);
7356ba597c5SAnurag S. Maskey 
7366ba597c5SAnurag S. Maskey 	return (B_FALSE);
7376ba597c5SAnurag S. Maskey }
7386ba597c5SAnurag S. Maskey 
7396ba597c5SAnurag S. Maskey /*
7406ba597c5SAnurag S. Maskey  * In rating activation conditions, we take the best-rated CONDITIONAL_ANY
7416ba597c5SAnurag S. Maskey  * condition, or sum all the CONDITIONAL_ALL condition ratings. This allows
7426ba597c5SAnurag S. Maskey  * us to compare between location activation conditions to pick the best.
7436ba597c5SAnurag S. Maskey  */
7446ba597c5SAnurag S. Maskey uint64_t
7456ba597c5SAnurag S. Maskey nwamd_rate_conditions(nwam_activation_mode_t activation_mode,
7466ba597c5SAnurag S. Maskey     char **conditions, uint_t num_conditions)
7476ba597c5SAnurag S. Maskey {
7486ba597c5SAnurag S. Maskey 	nwam_condition_t condition;
7496ba597c5SAnurag S. Maskey 	nwam_condition_object_type_t object_type;
7506ba597c5SAnurag S. Maskey 	char *object_name;
7516ba597c5SAnurag S. Maskey 	int i;
7526ba597c5SAnurag S. Maskey 	uint64_t rating = 0, total_rating = 0;
7536ba597c5SAnurag S. Maskey 
7546ba597c5SAnurag S. Maskey 	for (i = 0; i < num_conditions; i++) {
7556ba597c5SAnurag S. Maskey 
7566ba597c5SAnurag S. Maskey 		object_name = NULL;
7576ba597c5SAnurag S. Maskey 		if (nwam_condition_string_to_condition(conditions[i],
7586ba597c5SAnurag S. Maskey 		    &object_type, &condition, &object_name) != NWAM_SUCCESS ||
7596ba597c5SAnurag S. Maskey 		    nwam_condition_rate(object_type, condition, &rating)
7606ba597c5SAnurag S. Maskey 		    != NWAM_SUCCESS) {
7616ba597c5SAnurag S. Maskey 			nlog(LOG_ERR, "nwamd_rate_conditions: could not rate "
7626ba597c5SAnurag S. Maskey 			    "condition");
7636ba597c5SAnurag S. Maskey 			free(object_name);
7646ba597c5SAnurag S. Maskey 			return (0);
7656ba597c5SAnurag S. Maskey 		}
7666ba597c5SAnurag S. Maskey 		free(object_name);
7676ba597c5SAnurag S. Maskey 
7686ba597c5SAnurag S. Maskey 		if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY) {
7696ba597c5SAnurag S. Maskey 			if (rating > total_rating)
7706ba597c5SAnurag S. Maskey 				total_rating = rating;
7716ba597c5SAnurag S. Maskey 		} else if (activation_mode ==
7726ba597c5SAnurag S. Maskey 		    NWAM_ACTIVATION_MODE_CONDITIONAL_ALL) {
7736ba597c5SAnurag S. Maskey 			total_rating += rating;
7746ba597c5SAnurag S. Maskey 		}
7756ba597c5SAnurag S. Maskey 	}
7766ba597c5SAnurag S. Maskey 	return (total_rating);
7776ba597c5SAnurag S. Maskey }
7786ba597c5SAnurag S. Maskey 
7796ba597c5SAnurag S. Maskey /*
7806ba597c5SAnurag S. Maskey  * Different from nwamd_triggered_check_all_conditions() in that this
7816ba597c5SAnurag S. Maskey  * function enqueues a timed check event.
7826ba597c5SAnurag S. Maskey  */
7836ba597c5SAnurag S. Maskey void
7846ba597c5SAnurag S. Maskey nwamd_set_timed_check_all_conditions(void)
7856ba597c5SAnurag S. Maskey {
7866ba597c5SAnurag S. Maskey 	nwamd_event_t check_event = nwamd_event_init
7876ba597c5SAnurag S. Maskey 	    (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN,
7886ba597c5SAnurag S. Maskey 	    0, NULL);
7896ba597c5SAnurag S. Maskey 	if (check_event != NULL) {
7906ba597c5SAnurag S. Maskey 		/* Add another timed event to recheck conditions */
7916ba597c5SAnurag S. Maskey 		nwamd_event_enqueue_timed(check_event,
7926ba597c5SAnurag S. Maskey 		    condition_check_interval > CONDITION_CHECK_INTERVAL_MIN ?
7936ba597c5SAnurag S. Maskey 		    condition_check_interval : CONDITION_CHECK_INTERVAL_MIN);
7946ba597c5SAnurag S. Maskey 	}
7956ba597c5SAnurag S. Maskey }
7966ba597c5SAnurag S. Maskey 
7976ba597c5SAnurag S. Maskey /*
7986ba597c5SAnurag S. Maskey  * Does not enqueue another check event.
7996ba597c5SAnurag S. Maskey  */
8006ba597c5SAnurag S. Maskey void
8016ba597c5SAnurag S. Maskey nwamd_check_all_conditions(void)
8026ba597c5SAnurag S. Maskey {
8036ba597c5SAnurag S. Maskey 	nwamd_enm_check_conditions();
8046ba597c5SAnurag S. Maskey 	nwamd_loc_check_conditions();
8056ba597c5SAnurag S. Maskey }
8066ba597c5SAnurag S. Maskey 
8076ba597c5SAnurag S. Maskey void
8086ba597c5SAnurag S. Maskey nwamd_create_timed_condition_check_event(void)
8096ba597c5SAnurag S. Maskey {
8106ba597c5SAnurag S. Maskey 	nwamd_event_t check_event = nwamd_event_init
8116ba597c5SAnurag S. Maskey 	    (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN,
8126ba597c5SAnurag S. Maskey 	    0, NULL);
8136ba597c5SAnurag S. Maskey 	if (check_event != NULL)
8146ba597c5SAnurag S. Maskey 		nwamd_event_enqueue(check_event);
8156ba597c5SAnurag S. Maskey }
8166ba597c5SAnurag S. Maskey 
8176ba597c5SAnurag S. Maskey void
8186ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(uint32_t when)
8196ba597c5SAnurag S. Maskey {
8206ba597c5SAnurag S. Maskey 	nwamd_event_t check_event;
8216ba597c5SAnurag S. Maskey 
8226ba597c5SAnurag S. Maskey 	if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS,
8236ba597c5SAnurag S. Maskey 	    NWAM_OBJECT_TYPE_UNKNOWN, NULL)) {
8246ba597c5SAnurag S. Maskey 		check_event = nwamd_event_init
8256ba597c5SAnurag S. Maskey 		    (NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS,
8266ba597c5SAnurag S. Maskey 		    NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL);
8276ba597c5SAnurag S. Maskey 		if (check_event != NULL)
8286ba597c5SAnurag S. Maskey 			nwamd_event_enqueue_timed(check_event, when);
8296ba597c5SAnurag S. Maskey 	}
8306ba597c5SAnurag S. Maskey }
831