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 /* 23f6da83d4SAnurag 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 403f6da83d4SAnurag S. Maskey /* 404f6da83d4SAnurag S. Maskey * Given a string representation of an IPv4 or IPv6 address returns the 405f6da83d4SAnurag S. Maskey * sockaddr representation. Note that 'sockaddr' should point at the correct 406f6da83d4SAnurag S. Maskey * sockaddr structure for the address family (sockaddr_in for AF_INET or 407f6da83d4SAnurag S. Maskey * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage 408f6da83d4SAnurag S. Maskey * structure. 409f6da83d4SAnurag S. Maskey */ 410f6da83d4SAnurag S. Maskey static struct sockaddr_storage * 411f6da83d4SAnurag S. Maskey nwamd_str2sockaddr(sa_family_t af, const char *straddr, 412f6da83d4SAnurag S. Maskey struct sockaddr_storage *addr) 413f6da83d4SAnurag S. Maskey { 414f6da83d4SAnurag S. Maskey struct sockaddr_in *sin; 415f6da83d4SAnurag S. Maskey struct sockaddr_in6 *sin6; 416f6da83d4SAnurag S. Maskey int err; 417f6da83d4SAnurag S. Maskey 418f6da83d4SAnurag S. Maskey if (af == AF_INET) { 419f6da83d4SAnurag S. Maskey sin = (struct sockaddr_in *)addr; 420f6da83d4SAnurag S. Maskey sin->sin_family = AF_INET; 421f6da83d4SAnurag S. Maskey err = inet_pton(AF_INET, straddr, &sin->sin_addr); 422f6da83d4SAnurag S. Maskey } else if (af == AF_INET6) { 423f6da83d4SAnurag S. Maskey sin6 = (struct sockaddr_in6 *)addr; 424f6da83d4SAnurag S. Maskey sin6->sin6_family = AF_INET6; 425f6da83d4SAnurag S. Maskey err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr); 426f6da83d4SAnurag S. Maskey } else { 427f6da83d4SAnurag S. Maskey errno = EINVAL; 428f6da83d4SAnurag S. Maskey return (NULL); 429f6da83d4SAnurag S. Maskey } 430f6da83d4SAnurag S. Maskey return (err == 1 ? addr : NULL); 431f6da83d4SAnurag S. Maskey } 432f6da83d4SAnurag 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 441f6da83d4SAnurag 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; 444*64639aafSDarren Reed struct sockaddr_in6 addr6; 445*64639aafSDarren Reed struct sockaddr_in addr; 4466ba597c5SAnurag S. Maskey boolean_t match = B_FALSE; 4476ba597c5SAnurag S. Maskey uchar_t *addr1, *addr2; 4486ba597c5SAnurag S. Maskey 449f6da83d4SAnurag S. Maskey if (family == AF_INET) { 450*64639aafSDarren Reed (void) memcpy(&addr, ifa->ifa_addr, sizeof (addr)); 451*64639aafSDarren Reed addr1 = (uchar_t *)(&addr.sin_addr.s_addr); 4526ba597c5SAnurag S. Maskey addr2 = (uchar_t *)&(((struct sockaddr_in *) 4536ba597c5SAnurag S. Maskey &(wa->sockaddr))->sin_addr.s_addr); 4546ba597c5SAnurag S. Maskey } else { 455*64639aafSDarren Reed (void) memcpy(&addr6, ifa->ifa_addr, sizeof (addr6)); 456*64639aafSDarren Reed addr1 = (uchar_t *)(&addr6.sin6_addr.s6_addr); 4576ba597c5SAnurag S. Maskey addr2 = (uchar_t *)&(((struct sockaddr_in6 *) 4586ba597c5SAnurag S. Maskey &(wa->sockaddr))->sin6_addr.s6_addr); 4596ba597c5SAnurag S. Maskey } 4606ba597c5SAnurag S. Maskey 4616ba597c5SAnurag S. Maskey match = prefixmatch(addr1, addr2, wa->prefixlen); 4626ba597c5SAnurag S. Maskey 4636ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "check_ipaddr: match %d\n", match); 4646ba597c5SAnurag S. Maskey switch (wa->condition) { 4656ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS: 4666ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_IN_RANGE: 4676ba597c5SAnurag S. Maskey wa->res = match; 4686ba597c5SAnurag S. Maskey if (match) 4696ba597c5SAnurag S. Maskey return (1); 4706ba597c5SAnurag S. Maskey return (0); 4716ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_NOT: 4726ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_NOT_IN_RANGE: 4736ba597c5SAnurag S. Maskey wa->res = !match; 4746ba597c5SAnurag S. Maskey return (0); 4756ba597c5SAnurag S. Maskey default: 4766ba597c5SAnurag S. Maskey return (0); 4776ba597c5SAnurag S. Maskey } 4786ba597c5SAnurag S. Maskey } 4796ba597c5SAnurag S. Maskey 4806ba597c5SAnurag S. Maskey static boolean_t 4816ba597c5SAnurag S. Maskey test_condition_ip_address(nwam_condition_t condition, 4826ba597c5SAnurag S. Maskey const char *ip_address_string) 4836ba597c5SAnurag S. Maskey { 484f6da83d4SAnurag S. Maskey sa_family_t family; 4856ba597c5SAnurag S. Maskey char *copy, *ip_address, *prefixlen_string, *lasts; 4866ba597c5SAnurag S. Maskey struct nwamd_ipaddr_condition_walk_arg wa; 487f6da83d4SAnurag S. Maskey struct ifaddrs *ifap, *ifa; 4886ba597c5SAnurag S. Maskey 4896ba597c5SAnurag S. Maskey if ((copy = strdup(ip_address_string)) == NULL) 4906ba597c5SAnurag S. Maskey return (B_FALSE); 4916ba597c5SAnurag S. Maskey 4926ba597c5SAnurag S. Maskey if ((ip_address = strtok_r(copy, " \t/", &lasts)) == NULL) { 4936ba597c5SAnurag S. Maskey free(copy); 4946ba597c5SAnurag S. Maskey return (B_FALSE); 4956ba597c5SAnurag S. Maskey } 4966ba597c5SAnurag S. Maskey 4976ba597c5SAnurag S. Maskey prefixlen_string = strtok_r(NULL, " \t", &lasts); 4986ba597c5SAnurag S. Maskey 499f6da83d4SAnurag S. Maskey if (nwamd_str2sockaddr(AF_INET, ip_address, &wa.sockaddr) != NULL) { 500f6da83d4SAnurag S. Maskey family = AF_INET; 5016ba597c5SAnurag S. Maskey wa.prefixlen = IP_ABITS; 502f6da83d4SAnurag S. Maskey } else if (nwamd_str2sockaddr(AF_INET6, ip_address, &wa.sockaddr) 503f6da83d4SAnurag S. Maskey != NULL) { 504f6da83d4SAnurag S. Maskey family = AF_INET6; 5056ba597c5SAnurag S. Maskey wa.prefixlen = IPV6_ABITS; 5066ba597c5SAnurag S. Maskey } else { 5076ba597c5SAnurag S. Maskey nlog(LOG_ERR, "test_condition_ip_address: " 508f6da83d4SAnurag S. Maskey "nwamd_str2sockaddr failed for %s: %s", ip_address, 509f6da83d4SAnurag S. Maskey strerror(errno)); 5106ba597c5SAnurag S. Maskey free(copy); 5116ba597c5SAnurag S. Maskey return (B_FALSE); 5126ba597c5SAnurag S. Maskey } 5136ba597c5SAnurag S. Maskey 5146ba597c5SAnurag S. Maskey if (prefixlen_string != NULL) 5156ba597c5SAnurag S. Maskey wa.prefixlen = atoi(prefixlen_string); 5166ba597c5SAnurag S. Maskey 5176ba597c5SAnurag S. Maskey wa.condition = condition; 5186ba597c5SAnurag S. Maskey 5196ba597c5SAnurag S. Maskey switch (condition) { 5206ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS: 5216ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_IN_RANGE: 5226ba597c5SAnurag S. Maskey wa.res = B_FALSE; 5236ba597c5SAnurag S. Maskey break; 5246ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_NOT: 5256ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_NOT_IN_RANGE: 5266ba597c5SAnurag S. Maskey wa.res = B_TRUE; 5276ba597c5SAnurag S. Maskey break; 5286ba597c5SAnurag S. Maskey default: 5296ba597c5SAnurag S. Maskey free(copy); 5306ba597c5SAnurag S. Maskey return (B_FALSE); 5316ba597c5SAnurag S. Maskey } 5326ba597c5SAnurag S. Maskey free(copy); 5336ba597c5SAnurag S. Maskey 534f6da83d4SAnurag S. Maskey if (getifaddrs(&ifa) == -1) { 535f6da83d4SAnurag S. Maskey nlog(LOG_ERR, "test_condition_ip_address: " 536f6da83d4SAnurag S. Maskey "getifaddrs failed: %s", strerror(errno)); 537f6da83d4SAnurag S. Maskey return (wa.res); 538f6da83d4SAnurag S. Maskey } 539f6da83d4SAnurag S. Maskey for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { 540*64639aafSDarren Reed if (ifap->ifa_addr->sa_family != family) 541f6da83d4SAnurag S. Maskey continue; 542f6da83d4SAnurag S. Maskey if (check_ipaddr(family, ifap, &wa) == 1) 543f6da83d4SAnurag S. Maskey break; 544f6da83d4SAnurag S. Maskey } 545f6da83d4SAnurag S. Maskey freeifaddrs(ifa); 546f6da83d4SAnurag S. Maskey 5476ba597c5SAnurag S. Maskey return (wa.res); 5486ba597c5SAnurag S. Maskey } 5496ba597c5SAnurag S. Maskey 5506ba597c5SAnurag S. Maskey struct nwamd_wlan_condition_walk_arg { 5516ba597c5SAnurag S. Maskey nwam_condition_t condition; 5526ba597c5SAnurag S. Maskey const char *exp_essid; 5536ba597c5SAnurag S. Maskey const char *exp_bssid; 5546ba597c5SAnurag S. Maskey uint_t num_connected; 5556ba597c5SAnurag S. Maskey boolean_t res; 5566ba597c5SAnurag S. Maskey }; 5576ba597c5SAnurag S. Maskey 5586ba597c5SAnurag S. Maskey static int 5596ba597c5SAnurag S. Maskey check_wlan(const char *linkname, void *arg) 5606ba597c5SAnurag S. Maskey { 5616ba597c5SAnurag S. Maskey struct nwamd_wlan_condition_walk_arg *wa = arg; 5626ba597c5SAnurag S. Maskey datalink_id_t linkid; 5636ba597c5SAnurag S. Maskey dladm_wlan_linkattr_t attr; 5646ba597c5SAnurag S. Maskey dladm_status_t status; 5656ba597c5SAnurag S. Maskey char cur_essid[DLADM_STRSIZE]; 5666ba597c5SAnurag S. Maskey char cur_bssid[DLADM_STRSIZE]; 5676ba597c5SAnurag S. Maskey char errmsg[DLADM_STRSIZE]; 5686ba597c5SAnurag S. Maskey 5696ba597c5SAnurag S. Maskey if ((status = dladm_name2info(dld_handle, linkname, &linkid, NULL, NULL, 5706ba597c5SAnurag S. Maskey NULL)) != DLADM_STATUS_OK) { 5716ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "check_wlan: dladm_name2info() for %s " 5726ba597c5SAnurag S. Maskey "failed: %s", linkname, 5736ba597c5SAnurag S. Maskey dladm_status2str(status, errmsg)); 5746ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 5756ba597c5SAnurag S. Maskey } 5766ba597c5SAnurag S. Maskey 5776ba597c5SAnurag S. Maskey status = dladm_wlan_get_linkattr(dld_handle, linkid, &attr); 5786ba597c5SAnurag S. Maskey if (status != DLADM_STATUS_OK) { 5796ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "check_wlan: dladm_wlan_get_linkattr() for %s " 5806ba597c5SAnurag S. Maskey "failed: %s", linkname, 5816ba597c5SAnurag S. Maskey dladm_status2str(status, errmsg)); 5826ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 5836ba597c5SAnurag S. Maskey } 5846ba597c5SAnurag S. Maskey if (attr.la_status == DLADM_WLAN_LINK_DISCONNECTED) 5856ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 5866ba597c5SAnurag S. Maskey 5876ba597c5SAnurag S. Maskey wa->num_connected++; 5886ba597c5SAnurag S. Maskey 5896ba597c5SAnurag S. Maskey if (wa->exp_essid != NULL) { 5906ba597c5SAnurag S. Maskey /* Is the NIC associated with the expected access point? */ 5916ba597c5SAnurag S. Maskey (void) dladm_wlan_essid2str(&attr.la_wlan_attr.wa_essid, 5926ba597c5SAnurag S. Maskey cur_essid); 5936ba597c5SAnurag S. Maskey switch (wa->condition) { 5946ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS: 5956ba597c5SAnurag S. Maskey wa->res = strcmp(cur_essid, wa->exp_essid) == 0; 5966ba597c5SAnurag S. Maskey if (wa->res) 5976ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 5986ba597c5SAnurag S. Maskey break; 5996ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_NOT: 6006ba597c5SAnurag S. Maskey wa->res = strcmp(cur_essid, wa->exp_essid) != 0; 6016ba597c5SAnurag S. Maskey if (!wa->res) 6026ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6036ba597c5SAnurag S. Maskey break; 6046ba597c5SAnurag S. Maskey case NWAM_CONDITION_CONTAINS: 6056ba597c5SAnurag S. Maskey wa->res = strstr(cur_essid, wa->exp_essid) != NULL; 6066ba597c5SAnurag S. Maskey if (wa->res) 6076ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6086ba597c5SAnurag S. Maskey break; 6096ba597c5SAnurag S. Maskey case NWAM_CONDITION_DOES_NOT_CONTAIN: 6106ba597c5SAnurag S. Maskey wa->res = strstr(cur_essid, wa->exp_essid) == NULL; 6116ba597c5SAnurag S. Maskey if (!wa->res) 6126ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6136ba597c5SAnurag S. Maskey break; 6146ba597c5SAnurag S. Maskey default: 6156ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6166ba597c5SAnurag S. Maskey } 6176ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 6186ba597c5SAnurag S. Maskey } 6196ba597c5SAnurag S. Maskey if (wa->exp_bssid != NULL) { 6206ba597c5SAnurag S. Maskey /* Is the NIC associated with the expected access point? */ 6216ba597c5SAnurag S. Maskey (void) dladm_wlan_bssid2str(&attr.la_wlan_attr.wa_bssid, 6226ba597c5SAnurag S. Maskey cur_bssid); 6236ba597c5SAnurag S. Maskey switch (wa->condition) { 6246ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS: 6256ba597c5SAnurag S. Maskey wa->res = strcmp(cur_bssid, wa->exp_bssid) == 0; 6266ba597c5SAnurag S. Maskey if (wa->res) 6276ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6286ba597c5SAnurag S. Maskey break; 6296ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS_NOT: 6306ba597c5SAnurag S. Maskey wa->res = strcmp(cur_bssid, wa->exp_bssid) != 0; 6316ba597c5SAnurag S. Maskey if (!wa->res) 6326ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6336ba597c5SAnurag S. Maskey break; 6346ba597c5SAnurag S. Maskey default: 6356ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6366ba597c5SAnurag S. Maskey } 6376ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 6386ba597c5SAnurag S. Maskey } 6396ba597c5SAnurag S. Maskey /* 6406ba597c5SAnurag S. Maskey * Neither an ESSID or BSSID match is required - being connected to a 6416ba597c5SAnurag S. Maskey * WLAN is enough. 6426ba597c5SAnurag S. Maskey */ 6436ba597c5SAnurag S. Maskey switch (wa->condition) { 6446ba597c5SAnurag S. Maskey case NWAM_CONDITION_IS: 6456ba597c5SAnurag S. Maskey wa->res = B_TRUE; 6466ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6476ba597c5SAnurag S. Maskey default: 6486ba597c5SAnurag S. Maskey wa->res = B_FALSE; 6496ba597c5SAnurag S. Maskey return (DLADM_WALK_TERMINATE); 6506ba597c5SAnurag S. Maskey } 6516ba597c5SAnurag S. Maskey /*NOTREACHED*/ 6526ba597c5SAnurag S. Maskey return (DLADM_WALK_CONTINUE); 6536ba597c5SAnurag S. Maskey } 6546ba597c5SAnurag S. Maskey 6556ba597c5SAnurag S. Maskey static boolean_t 6566ba597c5SAnurag S. Maskey test_condition_wireless_essid(nwam_condition_t condition, 6576ba597c5SAnurag S. Maskey const char *essid) 6586ba597c5SAnurag S. Maskey { 6596ba597c5SAnurag S. Maskey struct nwamd_wlan_condition_walk_arg wa; 6606ba597c5SAnurag S. Maskey 6616ba597c5SAnurag S. Maskey wa.condition = condition; 6626ba597c5SAnurag S. Maskey wa.exp_essid = essid; 6636ba597c5SAnurag S. Maskey wa.exp_bssid = NULL; 6646ba597c5SAnurag S. Maskey wa.num_connected = 0; 6656ba597c5SAnurag S. Maskey wa.res = B_FALSE; 6666ba597c5SAnurag S. Maskey 6676ba597c5SAnurag S. Maskey (void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS, 6686ba597c5SAnurag S. Maskey DL_WIFI, DLADM_OPT_ACTIVE); 6696ba597c5SAnurag S. Maskey 6706ba597c5SAnurag S. Maskey return (wa.num_connected > 0 && wa.res == B_TRUE); 6716ba597c5SAnurag S. Maskey } 6726ba597c5SAnurag S. Maskey 6736ba597c5SAnurag S. Maskey static boolean_t 6746ba597c5SAnurag S. Maskey test_condition_wireless_bssid(nwam_condition_t condition, 6756ba597c5SAnurag S. Maskey const char *bssid) 6766ba597c5SAnurag S. Maskey { 6776ba597c5SAnurag S. Maskey struct nwamd_wlan_condition_walk_arg wa; 6786ba597c5SAnurag S. Maskey 6796ba597c5SAnurag S. Maskey wa.condition = condition; 6806ba597c5SAnurag S. Maskey wa.exp_bssid = bssid; 6816ba597c5SAnurag S. Maskey wa.exp_essid = NULL; 6826ba597c5SAnurag S. Maskey wa.num_connected = 0; 6836ba597c5SAnurag S. Maskey wa.res = B_FALSE; 6846ba597c5SAnurag S. Maskey 6856ba597c5SAnurag S. Maskey (void) dladm_walk(check_wlan, dld_handle, &wa, DATALINK_CLASS_PHYS, 6866ba597c5SAnurag S. Maskey DL_WIFI, DLADM_OPT_ACTIVE); 6876ba597c5SAnurag S. Maskey 6886ba597c5SAnurag S. Maskey return (wa.num_connected > 0 && wa.res == B_TRUE); 6896ba597c5SAnurag S. Maskey } 6906ba597c5SAnurag S. Maskey 6916ba597c5SAnurag S. Maskey /* 6926ba597c5SAnurag S. Maskey * This function takes an activation mode and a string representation of a 6936ba597c5SAnurag S. Maskey * condition and evaluates it. 6946ba597c5SAnurag S. Maskey */ 6956ba597c5SAnurag S. Maskey boolean_t 6966ba597c5SAnurag S. Maskey nwamd_check_conditions(nwam_activation_mode_t activation_mode, 6976ba597c5SAnurag S. Maskey char **condition_strings, uint_t num_conditions) 6986ba597c5SAnurag S. Maskey { 6996ba597c5SAnurag S. Maskey boolean_t ret; 7006ba597c5SAnurag S. Maskey nwam_condition_t condition; 7016ba597c5SAnurag S. Maskey nwam_condition_object_type_t object_type; 7026ba597c5SAnurag S. Maskey char *object_name; 7036ba597c5SAnurag S. Maskey int i, j; 7046ba597c5SAnurag S. Maskey 7056ba597c5SAnurag S. Maskey for (i = 0; i < num_conditions; i++) { 7066ba597c5SAnurag S. Maskey 7076ba597c5SAnurag S. Maskey if (nwam_condition_string_to_condition(condition_strings[i], 7086ba597c5SAnurag S. Maskey &object_type, &condition, &object_name) != NWAM_SUCCESS) { 7096ba597c5SAnurag S. Maskey nlog(LOG_ERR, "check_conditions: invalid condition %s", 7106ba597c5SAnurag S. Maskey condition_strings[i]); 7116ba597c5SAnurag S. Maskey return (B_FALSE); 7126ba597c5SAnurag S. Maskey } 7136ba597c5SAnurag S. Maskey ret = B_FALSE; 7146ba597c5SAnurag S. Maskey 7156ba597c5SAnurag S. Maskey for (j = 0; j < (sizeof (condition_map) / 7166ba597c5SAnurag S. Maskey sizeof (struct nwamd_condition_map)); j++) { 7176ba597c5SAnurag S. Maskey if (condition_map[j].object_type == object_type) 7186ba597c5SAnurag S. Maskey ret = condition_map[j].condition_func(condition, 7196ba597c5SAnurag S. Maskey object_name); 7206ba597c5SAnurag S. Maskey } 7216ba597c5SAnurag S. Maskey 7226ba597c5SAnurag S. Maskey free(object_name); 7236ba597c5SAnurag S. Maskey 7246ba597c5SAnurag S. Maskey if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY && 7256ba597c5SAnurag S. Maskey ret) { 7266ba597c5SAnurag S. Maskey return (B_TRUE); 7276ba597c5SAnurag S. Maskey } 7286ba597c5SAnurag S. Maskey if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL && 7296ba597c5SAnurag S. Maskey !ret) { 7306ba597c5SAnurag S. Maskey return (B_FALSE); 7316ba597c5SAnurag S. Maskey } 7326ba597c5SAnurag S. Maskey } 7336ba597c5SAnurag S. Maskey if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY && ret) 7346ba597c5SAnurag S. Maskey return (B_TRUE); 7356ba597c5SAnurag S. Maskey if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ALL && ret) 7366ba597c5SAnurag S. Maskey return (B_TRUE); 7376ba597c5SAnurag S. Maskey 7386ba597c5SAnurag S. Maskey return (B_FALSE); 7396ba597c5SAnurag S. Maskey } 7406ba597c5SAnurag S. Maskey 7416ba597c5SAnurag S. Maskey /* 7426ba597c5SAnurag S. Maskey * In rating activation conditions, we take the best-rated CONDITIONAL_ANY 7436ba597c5SAnurag S. Maskey * condition, or sum all the CONDITIONAL_ALL condition ratings. This allows 7446ba597c5SAnurag S. Maskey * us to compare between location activation conditions to pick the best. 7456ba597c5SAnurag S. Maskey */ 7466ba597c5SAnurag S. Maskey uint64_t 7476ba597c5SAnurag S. Maskey nwamd_rate_conditions(nwam_activation_mode_t activation_mode, 7486ba597c5SAnurag S. Maskey char **conditions, uint_t num_conditions) 7496ba597c5SAnurag S. Maskey { 7506ba597c5SAnurag S. Maskey nwam_condition_t condition; 7516ba597c5SAnurag S. Maskey nwam_condition_object_type_t object_type; 7526ba597c5SAnurag S. Maskey char *object_name; 7536ba597c5SAnurag S. Maskey int i; 7546ba597c5SAnurag S. Maskey uint64_t rating = 0, total_rating = 0; 7556ba597c5SAnurag S. Maskey 7566ba597c5SAnurag S. Maskey for (i = 0; i < num_conditions; i++) { 7576ba597c5SAnurag S. Maskey 7586ba597c5SAnurag S. Maskey object_name = NULL; 7596ba597c5SAnurag S. Maskey if (nwam_condition_string_to_condition(conditions[i], 7606ba597c5SAnurag S. Maskey &object_type, &condition, &object_name) != NWAM_SUCCESS || 7616ba597c5SAnurag S. Maskey nwam_condition_rate(object_type, condition, &rating) 7626ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 7636ba597c5SAnurag S. Maskey nlog(LOG_ERR, "nwamd_rate_conditions: could not rate " 7646ba597c5SAnurag S. Maskey "condition"); 7656ba597c5SAnurag S. Maskey free(object_name); 7666ba597c5SAnurag S. Maskey return (0); 7676ba597c5SAnurag S. Maskey } 7686ba597c5SAnurag S. Maskey free(object_name); 7696ba597c5SAnurag S. Maskey 7706ba597c5SAnurag S. Maskey if (activation_mode == NWAM_ACTIVATION_MODE_CONDITIONAL_ANY) { 7716ba597c5SAnurag S. Maskey if (rating > total_rating) 7726ba597c5SAnurag S. Maskey total_rating = rating; 7736ba597c5SAnurag S. Maskey } else if (activation_mode == 7746ba597c5SAnurag S. Maskey NWAM_ACTIVATION_MODE_CONDITIONAL_ALL) { 7756ba597c5SAnurag S. Maskey total_rating += rating; 7766ba597c5SAnurag S. Maskey } 7776ba597c5SAnurag S. Maskey } 7786ba597c5SAnurag S. Maskey return (total_rating); 7796ba597c5SAnurag S. Maskey } 7806ba597c5SAnurag S. Maskey 7816ba597c5SAnurag S. Maskey /* 7826ba597c5SAnurag S. Maskey * Different from nwamd_triggered_check_all_conditions() in that this 7836ba597c5SAnurag S. Maskey * function enqueues a timed check event. 7846ba597c5SAnurag S. Maskey */ 7856ba597c5SAnurag S. Maskey void 7866ba597c5SAnurag S. Maskey nwamd_set_timed_check_all_conditions(void) 7876ba597c5SAnurag S. Maskey { 7886ba597c5SAnurag S. Maskey nwamd_event_t check_event = nwamd_event_init 7896ba597c5SAnurag S. Maskey (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN, 7906ba597c5SAnurag S. Maskey 0, NULL); 7916ba597c5SAnurag S. Maskey if (check_event != NULL) { 7926ba597c5SAnurag S. Maskey /* Add another timed event to recheck conditions */ 7936ba597c5SAnurag S. Maskey nwamd_event_enqueue_timed(check_event, 7946ba597c5SAnurag S. Maskey condition_check_interval > CONDITION_CHECK_INTERVAL_MIN ? 7956ba597c5SAnurag S. Maskey condition_check_interval : CONDITION_CHECK_INTERVAL_MIN); 7966ba597c5SAnurag S. Maskey } 7976ba597c5SAnurag S. Maskey } 7986ba597c5SAnurag S. Maskey 7996ba597c5SAnurag S. Maskey /* 8006ba597c5SAnurag S. Maskey * Does not enqueue another check event. 8016ba597c5SAnurag S. Maskey */ 8026ba597c5SAnurag S. Maskey void 8036ba597c5SAnurag S. Maskey nwamd_check_all_conditions(void) 8046ba597c5SAnurag S. Maskey { 8056ba597c5SAnurag S. Maskey nwamd_enm_check_conditions(); 8066ba597c5SAnurag S. Maskey nwamd_loc_check_conditions(); 8076ba597c5SAnurag S. Maskey } 8086ba597c5SAnurag S. Maskey 8096ba597c5SAnurag S. Maskey void 8106ba597c5SAnurag S. Maskey nwamd_create_timed_condition_check_event(void) 8116ba597c5SAnurag S. Maskey { 8126ba597c5SAnurag S. Maskey nwamd_event_t check_event = nwamd_event_init 8136ba597c5SAnurag S. Maskey (NWAM_EVENT_TYPE_TIMED_CHECK_CONDITIONS, NWAM_OBJECT_TYPE_UNKNOWN, 8146ba597c5SAnurag S. Maskey 0, NULL); 8156ba597c5SAnurag S. Maskey if (check_event != NULL) 8166ba597c5SAnurag S. Maskey nwamd_event_enqueue(check_event); 8176ba597c5SAnurag S. Maskey } 8186ba597c5SAnurag S. Maskey 8196ba597c5SAnurag S. Maskey void 8206ba597c5SAnurag S. Maskey nwamd_create_triggered_condition_check_event(uint32_t when) 8216ba597c5SAnurag S. Maskey { 8226ba597c5SAnurag S. Maskey nwamd_event_t check_event; 8236ba597c5SAnurag S. Maskey 8246ba597c5SAnurag S. Maskey if (!nwamd_event_enqueued(NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS, 8256ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_UNKNOWN, NULL)) { 8266ba597c5SAnurag S. Maskey check_event = nwamd_event_init 8276ba597c5SAnurag S. Maskey (NWAM_EVENT_TYPE_TRIGGERED_CHECK_CONDITIONS, 8286ba597c5SAnurag S. Maskey NWAM_OBJECT_TYPE_UNKNOWN, 0, NULL); 8296ba597c5SAnurag S. Maskey if (check_event != NULL) 8306ba597c5SAnurag S. Maskey nwamd_event_enqueue_timed(check_event, when); 8316ba597c5SAnurag S. Maskey } 8326ba597c5SAnurag S. Maskey } 833