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 <ctype.h> 276ba597c5SAnurag S. Maskey #include <errno.h> 286ba597c5SAnurag S. Maskey #include <limits.h> 296ba597c5SAnurag S. Maskey #include <stdio.h> 306ba597c5SAnurag S. Maskey #include <stdlib.h> 316ba597c5SAnurag S. Maskey #include <string.h> 326ba597c5SAnurag S. Maskey #include <libdladm.h> 336ba597c5SAnurag S. Maskey #include <libdllink.h> 346ba597c5SAnurag S. Maskey #include <libdlwlan.h> 356ba597c5SAnurag S. Maskey #include <libgen.h> 366ba597c5SAnurag S. Maskey #include <libnwam.h> 376ba597c5SAnurag S. Maskey 386ba597c5SAnurag S. Maskey #include "events.h" 396ba597c5SAnurag S. Maskey #include "known_wlans.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 * known_wlans.c - contains routines which handle the known WLAN abstraction. 466ba597c5SAnurag S. Maskey */ 476ba597c5SAnurag S. Maskey 486ba597c5SAnurag S. Maskey #define KNOWN_WIFI_NETS_FILE "/etc/nwam/known_wifi_nets" 496ba597c5SAnurag S. Maskey 506ba597c5SAnurag S. Maskey /* enum for parsing each line of /etc/nwam/known_wifi_nets */ 516ba597c5SAnurag S. Maskey typedef enum { 526ba597c5SAnurag S. Maskey ESSID = 0, 536ba597c5SAnurag S. Maskey BSSID, 546ba597c5SAnurag S. Maskey MAX_FIELDS 556ba597c5SAnurag S. Maskey } known_wifi_nets_fields_t; 566ba597c5SAnurag S. Maskey 576ba597c5SAnurag S. Maskey /* Structure for one BSSID */ 586ba597c5SAnurag S. Maskey typedef struct bssid { 596ba597c5SAnurag S. Maskey struct qelem bssid_links; 606ba597c5SAnurag S. Maskey char *bssid; 616ba597c5SAnurag S. Maskey } bssid_t; 626ba597c5SAnurag S. Maskey 636ba597c5SAnurag S. Maskey /* Structure for an ESSID and its BSSIDs */ 646ba597c5SAnurag S. Maskey typedef struct kw { 656ba597c5SAnurag S. Maskey struct qelem kw_links; 666ba597c5SAnurag S. Maskey char kw_essid[NWAM_MAX_NAME_LEN]; 676ba597c5SAnurag S. Maskey uint32_t kw_num_bssids; 686ba597c5SAnurag S. Maskey struct qelem kw_bssids; 696ba597c5SAnurag S. Maskey } kw_t; 706ba597c5SAnurag S. Maskey 716ba597c5SAnurag S. Maskey /* Holds the linked-list of ESSIDs to make Known WLANs out of */ 726ba597c5SAnurag S. Maskey static struct qelem kw_list; 736ba597c5SAnurag S. Maskey 746ba597c5SAnurag S. Maskey /* Used in walking secobjs looking for an ESSID prefix match. */ 756ba597c5SAnurag S. Maskey struct nwamd_secobj_arg { 766ba597c5SAnurag S. Maskey char nsa_essid_prefix[DLADM_WLAN_MAX_KEYNAME_LEN]; 776ba597c5SAnurag S. Maskey char nsa_keyname[DLADM_WLAN_MAX_KEYNAME_LEN]; 786ba597c5SAnurag S. Maskey dladm_wlan_key_t *nsa_key; 796ba597c5SAnurag S. Maskey uint64_t nsa_secmode; 806ba597c5SAnurag S. Maskey }; 816ba597c5SAnurag S. Maskey 826ba597c5SAnurag S. Maskey static void 836ba597c5SAnurag S. Maskey kw_list_init(void) 846ba597c5SAnurag S. Maskey { 856ba597c5SAnurag S. Maskey kw_list.q_forw = kw_list.q_back = &kw_list; 866ba597c5SAnurag S. Maskey } 876ba597c5SAnurag S. Maskey 886ba597c5SAnurag S. Maskey static void 896ba597c5SAnurag S. Maskey kw_list_free(void) 906ba597c5SAnurag S. Maskey { 916ba597c5SAnurag S. Maskey kw_t *kw; 926ba597c5SAnurag S. Maskey bssid_t *b; 936ba597c5SAnurag S. Maskey 946ba597c5SAnurag S. Maskey while (kw_list.q_forw != &kw_list) { 956ba597c5SAnurag S. Maskey kw = (kw_t *)kw_list.q_forw; 966ba597c5SAnurag S. Maskey 976ba597c5SAnurag S. Maskey /* free kw_bssids */ 986ba597c5SAnurag S. Maskey while (kw->kw_bssids.q_forw != &kw->kw_bssids) { 996ba597c5SAnurag S. Maskey b = (bssid_t *)kw->kw_bssids.q_forw; 1006ba597c5SAnurag S. Maskey remque(&b->bssid_links); 1016ba597c5SAnurag S. Maskey free(b->bssid); 1026ba597c5SAnurag S. Maskey free(b); 1036ba597c5SAnurag S. Maskey } 1046ba597c5SAnurag S. Maskey remque(&kw->kw_links); 1056ba597c5SAnurag S. Maskey free(kw); 1066ba597c5SAnurag S. Maskey } 1076ba597c5SAnurag S. Maskey } 1086ba597c5SAnurag S. Maskey 1096ba597c5SAnurag S. Maskey /* Returns the entry in kw_list for the given ESSID. NULL if non-existent */ 1106ba597c5SAnurag S. Maskey static kw_t * 1116ba597c5SAnurag S. Maskey kw_lookup(const char *essid) 1126ba597c5SAnurag S. Maskey { 1136ba597c5SAnurag S. Maskey kw_t *kw; 1146ba597c5SAnurag S. Maskey 1156ba597c5SAnurag S. Maskey if (essid == NULL) 1166ba597c5SAnurag S. Maskey return (NULL); 1176ba597c5SAnurag S. Maskey 1186ba597c5SAnurag S. Maskey for (kw = (kw_t *)kw_list.q_forw; 1196ba597c5SAnurag S. Maskey kw != (kw_t *)&kw_list; 1206ba597c5SAnurag S. Maskey kw = (kw_t *)kw->kw_links.q_forw) { 1216ba597c5SAnurag S. Maskey if (strcmp(essid, kw->kw_essid) == 0) 1226ba597c5SAnurag S. Maskey return (kw); 1236ba597c5SAnurag S. Maskey } 1246ba597c5SAnurag S. Maskey return (NULL); 1256ba597c5SAnurag S. Maskey } 1266ba597c5SAnurag S. Maskey 1276ba597c5SAnurag S. Maskey /* Adds an ESSID/BSSID combination to kw_list. Returns B_TRUE on success. */ 1286ba597c5SAnurag S. Maskey static boolean_t 1296ba597c5SAnurag S. Maskey kw_add(const char *essid, const char *bssid) 1306ba597c5SAnurag S. Maskey { 1316ba597c5SAnurag S. Maskey kw_t *kw; 1326ba597c5SAnurag S. Maskey bssid_t *b; 1336ba597c5SAnurag S. Maskey 1346ba597c5SAnurag S. Maskey if ((b = calloc(1, sizeof (bssid_t))) == NULL) { 1356ba597c5SAnurag S. Maskey nlog(LOG_ERR, "kw_add: cannot allocate for bssid_t: %m"); 1366ba597c5SAnurag S. Maskey return (B_FALSE); 1376ba597c5SAnurag S. Maskey } 1386ba597c5SAnurag S. Maskey if ((kw = calloc(1, sizeof (kw_t))) == NULL) { 1396ba597c5SAnurag S. Maskey nlog(LOG_ERR, "kw_add: cannot allocate for kw_t: %m"); 1406ba597c5SAnurag S. Maskey free(b); 1416ba597c5SAnurag S. Maskey return (B_FALSE); 1426ba597c5SAnurag S. Maskey } 1436ba597c5SAnurag S. Maskey kw->kw_bssids.q_forw = kw->kw_bssids.q_back = &kw->kw_bssids; 1446ba597c5SAnurag S. Maskey 1456ba597c5SAnurag S. Maskey b->bssid = strdup(bssid); 1466ba597c5SAnurag S. Maskey (void) strlcpy(kw->kw_essid, essid, sizeof (kw->kw_essid)); 1476ba597c5SAnurag S. Maskey kw->kw_num_bssids = 1; 1486ba597c5SAnurag S. Maskey 1496ba597c5SAnurag S. Maskey insque(&b->bssid_links, kw->kw_bssids.q_back); 1506ba597c5SAnurag S. Maskey insque(&kw->kw_links, kw_list.q_back); 1516ba597c5SAnurag S. Maskey 1526ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "kw_add: added Known WLAN %s, BSSID %s", essid, bssid); 1536ba597c5SAnurag S. Maskey return (B_TRUE); 1546ba597c5SAnurag S. Maskey } 1556ba597c5SAnurag S. Maskey 1566ba597c5SAnurag S. Maskey /* 1576ba597c5SAnurag S. Maskey * Add the BSSID to the given kw. Since /etc/nwam/known_wifi_nets is 1586ba597c5SAnurag S. Maskey * populated such that the wifi networks visited later are towards the end 1596ba597c5SAnurag S. Maskey * of the file, remove the give kw from its current position and append it 1606ba597c5SAnurag S. Maskey * to the end of kw_list. This ensures that kw_list is in the reverse 1616ba597c5SAnurag S. Maskey * order of visited wifi networks. Returns B_TRUE on success. 1626ba597c5SAnurag S. Maskey */ 1636ba597c5SAnurag S. Maskey static boolean_t 1646ba597c5SAnurag S. Maskey kw_update(kw_t *kw, const char *bssid) 1656ba597c5SAnurag S. Maskey { 1666ba597c5SAnurag S. Maskey bssid_t *b; 1676ba597c5SAnurag S. Maskey 1686ba597c5SAnurag S. Maskey if ((b = calloc(1, sizeof (bssid_t))) == NULL) { 1696ba597c5SAnurag S. Maskey nlog(LOG_ERR, "kw_update: cannot allocate for bssid_t: %m"); 1706ba597c5SAnurag S. Maskey return (B_FALSE); 1716ba597c5SAnurag S. Maskey } 1726ba597c5SAnurag S. Maskey 1736ba597c5SAnurag S. Maskey b->bssid = strdup(bssid); 1746ba597c5SAnurag S. Maskey insque(&b->bssid_links, kw->kw_bssids.q_back); 1756ba597c5SAnurag S. Maskey kw->kw_num_bssids++; 1766ba597c5SAnurag S. Maskey 1776ba597c5SAnurag S. Maskey /* remove kw from current position */ 1786ba597c5SAnurag S. Maskey remque(&kw->kw_links); 1796ba597c5SAnurag S. Maskey /* and insert at end */ 1806ba597c5SAnurag S. Maskey insque(&kw->kw_links, kw_list.q_back); 1816ba597c5SAnurag S. Maskey 1826ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "kw_update: appended BSSID %s to Known WLAN %s", 1836ba597c5SAnurag S. Maskey bssid, kw->kw_essid); 1846ba597c5SAnurag S. Maskey return (B_TRUE); 1856ba597c5SAnurag S. Maskey } 1866ba597c5SAnurag S. Maskey 1876ba597c5SAnurag S. Maskey /* 1886ba597c5SAnurag S. Maskey * Parses /etc/nwam/known_wifi_nets and populates kw_list, with the oldest 1896ba597c5SAnurag S. Maskey * wifi networks first in the list. Returns the number of unique entries 1906ba597c5SAnurag S. Maskey * in kw_list (to use for priority values). 1916ba597c5SAnurag S. Maskey */ 1926ba597c5SAnurag S. Maskey static int 1936ba597c5SAnurag S. Maskey parse_known_wifi_nets(void) 1946ba597c5SAnurag S. Maskey { 1956ba597c5SAnurag S. Maskey FILE *fp; 1966ba597c5SAnurag S. Maskey char line[LINE_MAX]; 1976ba597c5SAnurag S. Maskey char *cp, *tok[MAX_FIELDS]; 1986ba597c5SAnurag S. Maskey int lnum, num_kw = 0; 1996ba597c5SAnurag S. Maskey kw_t *kw; 2006ba597c5SAnurag S. Maskey 2016ba597c5SAnurag S. Maskey kw_list_init(); 2026ba597c5SAnurag S. Maskey 2036ba597c5SAnurag S. Maskey /* 2046ba597c5SAnurag S. Maskey * The file format is: 2056ba597c5SAnurag S. Maskey * essid\tbssid (essid followed by tab followed by bssid) 2066ba597c5SAnurag S. Maskey */ 2076ba597c5SAnurag S. Maskey fp = fopen(KNOWN_WIFI_NETS_FILE, "r"); 2086ba597c5SAnurag S. Maskey if (fp == NULL) 2096ba597c5SAnurag S. Maskey return (0); 2106ba597c5SAnurag S. Maskey for (lnum = 1; fgets(line, sizeof (line), fp) != NULL; lnum++) { 2116ba597c5SAnurag S. Maskey 2126ba597c5SAnurag S. Maskey cp = line; 2136ba597c5SAnurag S. Maskey while (isspace(*cp)) 2146ba597c5SAnurag S. Maskey cp++; 2156ba597c5SAnurag S. Maskey if (*cp == '#' || *cp == '\0') 2166ba597c5SAnurag S. Maskey continue; 2176ba597c5SAnurag S. Maskey 2186ba597c5SAnurag S. Maskey if (bufsplit(cp, MAX_FIELDS, tok) != MAX_FIELDS) { 2196ba597c5SAnurag S. Maskey syslog(LOG_ERR, "%s:%d: wrong number of tokens; " 2206ba597c5SAnurag S. Maskey "ignoring entry", KNOWN_WIFI_NETS_FILE, lnum); 2216ba597c5SAnurag S. Maskey continue; 2226ba597c5SAnurag S. Maskey } 2236ba597c5SAnurag S. Maskey 2246ba597c5SAnurag S. Maskey if ((kw = kw_lookup(tok[ESSID])) == NULL) { 2256ba597c5SAnurag S. Maskey if (!kw_add(tok[ESSID], tok[BSSID])) { 2266ba597c5SAnurag S. Maskey nlog(LOG_ERR, 2276ba597c5SAnurag S. Maskey "%s:%d: cannot add entry (%s,%s) to list", 2286ba597c5SAnurag S. Maskey KNOWN_WIFI_NETS_FILE, lnum, 2296ba597c5SAnurag S. Maskey tok[ESSID], tok[BSSID]); 2306ba597c5SAnurag S. Maskey } else { 2316ba597c5SAnurag S. Maskey num_kw++; 2326ba597c5SAnurag S. Maskey } 2336ba597c5SAnurag S. Maskey } else { 2346ba597c5SAnurag S. Maskey if (!kw_update(kw, tok[BSSID])) { 2356ba597c5SAnurag S. Maskey nlog(LOG_ERR, 2366ba597c5SAnurag S. Maskey "%s:%d:cannot update entry (%s,%s) to list", 2376ba597c5SAnurag S. Maskey KNOWN_WIFI_NETS_FILE, lnum, 2386ba597c5SAnurag S. Maskey tok[ESSID], tok[BSSID]); 2396ba597c5SAnurag S. Maskey } 2406ba597c5SAnurag S. Maskey } 2416ba597c5SAnurag S. Maskey /* next line ... */ 2426ba597c5SAnurag S. Maskey } 2436ba597c5SAnurag S. Maskey 2446ba597c5SAnurag S. Maskey (void) fclose(fp); 2456ba597c5SAnurag S. Maskey return (num_kw); 2466ba597c5SAnurag S. Maskey } 2476ba597c5SAnurag S. Maskey 2486ba597c5SAnurag S. Maskey /* 2496ba597c5SAnurag S. Maskey * Walk security objects looking for one that matches the essid prefix. 2506ba597c5SAnurag S. Maskey * Store the key and keyname if a match is found - we use the last match 2516ba597c5SAnurag S. Maskey * as the key for the known WLAN, since it is the most recently updated. 2526ba597c5SAnurag S. Maskey */ 2536ba597c5SAnurag S. Maskey /* ARGSUSED0 */ 2546ba597c5SAnurag S. Maskey static boolean_t 2556ba597c5SAnurag S. Maskey find_secobj_matching_prefix(dladm_handle_t dh, void *arg, 2566ba597c5SAnurag S. Maskey const char *secobjname) 2576ba597c5SAnurag S. Maskey { 2586ba597c5SAnurag S. Maskey struct nwamd_secobj_arg *nsa = arg; 2596ba597c5SAnurag S. Maskey 2606ba597c5SAnurag S. Maskey if (strncmp(nsa->nsa_essid_prefix, secobjname, 2616ba597c5SAnurag S. Maskey strlen(nsa->nsa_essid_prefix)) == 0) { 2626ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "find_secobj_matching_prefix: " 2636ba597c5SAnurag S. Maskey "found secobj with prefix %s : %s\n", 2646ba597c5SAnurag S. Maskey nsa->nsa_essid_prefix, secobjname); 2656ba597c5SAnurag S. Maskey /* Free last key found (if any) */ 2666ba597c5SAnurag S. Maskey if (nsa->nsa_key != NULL) 2676ba597c5SAnurag S. Maskey free(nsa->nsa_key); 2686ba597c5SAnurag S. Maskey /* Retrive key so we can get security mode */ 2696ba597c5SAnurag S. Maskey nsa->nsa_key = nwamd_wlan_get_key_named(secobjname, 0); 2706ba597c5SAnurag S. Maskey (void) strlcpy(nsa->nsa_keyname, secobjname, 2716ba597c5SAnurag S. Maskey sizeof (nsa->nsa_keyname)); 2726ba597c5SAnurag S. Maskey switch (nsa->nsa_key->wk_class) { 2736ba597c5SAnurag S. Maskey case DLADM_SECOBJ_CLASS_WEP: 2746ba597c5SAnurag S. Maskey nsa->nsa_secmode = DLADM_WLAN_SECMODE_WEP; 2756ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "find_secobj_matching_prefix: " 2766ba597c5SAnurag S. Maskey "got WEP key %s", nsa->nsa_keyname); 2776ba597c5SAnurag S. Maskey break; 2786ba597c5SAnurag S. Maskey case DLADM_SECOBJ_CLASS_WPA: 2796ba597c5SAnurag S. Maskey nsa->nsa_secmode = DLADM_WLAN_SECMODE_WPA; 2806ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "find_secobj_matching_prefix: " 2816ba597c5SAnurag S. Maskey "got WPA key %s", nsa->nsa_keyname); 2826ba597c5SAnurag S. Maskey break; 2836ba597c5SAnurag S. Maskey default: 2846ba597c5SAnurag S. Maskey /* shouldn't happen */ 2856ba597c5SAnurag S. Maskey nsa->nsa_secmode = DLADM_WLAN_SECMODE_NONE; 2866ba597c5SAnurag S. Maskey nlog(LOG_ERR, "find_secobj_matching_prefix: " 2876ba597c5SAnurag S. Maskey "key class for key %s was invalid", 2886ba597c5SAnurag S. Maskey nsa->nsa_keyname); 2896ba597c5SAnurag S. Maskey break; 2906ba597c5SAnurag S. Maskey } 2916ba597c5SAnurag S. Maskey } 2926ba597c5SAnurag S. Maskey return (B_TRUE); 2936ba597c5SAnurag S. Maskey } 2946ba597c5SAnurag S. Maskey 2956ba597c5SAnurag S. Maskey 2966ba597c5SAnurag S. Maskey /* Upgrade /etc/nwam/known_wifi_nets file to new libnwam-based config model */ 2976ba597c5SAnurag S. Maskey void 2986ba597c5SAnurag S. Maskey upgrade_known_wifi_nets_config(void) 2996ba597c5SAnurag S. Maskey { 3006ba597c5SAnurag S. Maskey kw_t *kw; 3016ba597c5SAnurag S. Maskey bssid_t *b; 3026ba597c5SAnurag S. Maskey nwam_known_wlan_handle_t kwh; 3036ba597c5SAnurag S. Maskey char **bssids; 3046ba597c5SAnurag S. Maskey nwam_error_t err; 3056ba597c5SAnurag S. Maskey uint64_t priority; 3066ba597c5SAnurag S. Maskey int i, num_kw; 3076ba597c5SAnurag S. Maskey struct nwamd_secobj_arg nsa; 3086ba597c5SAnurag S. Maskey 3096ba597c5SAnurag S. Maskey nlog(LOG_INFO, "Upgrading %s to Known WLANs", KNOWN_WIFI_NETS_FILE); 3106ba597c5SAnurag S. Maskey 3116ba597c5SAnurag S. Maskey /* Parse /etc/nwam/known_wifi_nets */ 3126ba597c5SAnurag S. Maskey num_kw = parse_known_wifi_nets(); 3136ba597c5SAnurag S. Maskey 3146ba597c5SAnurag S. Maskey /* Create Known WLANs for each unique ESSID */ 3156ba597c5SAnurag S. Maskey for (kw = (kw_t *)kw_list.q_forw, priority = num_kw-1; 3166ba597c5SAnurag S. Maskey kw != (kw_t *)&kw_list; 3176ba597c5SAnurag S. Maskey kw = (kw_t *)kw->kw_links.q_forw, priority--) { 3186ba597c5SAnurag S. Maskey nwam_value_t priorityval = NULL; 3196ba597c5SAnurag S. Maskey nwam_value_t bssidsval = NULL; 3206ba597c5SAnurag S. Maskey nwam_value_t secmodeval = NULL; 3216ba597c5SAnurag S. Maskey nwam_value_t keynameval = NULL; 3226ba597c5SAnurag S. Maskey 3236ba597c5SAnurag S. Maskey nlog(LOG_DEBUG, "Creating Known WLAN %s", kw->kw_essid); 3246ba597c5SAnurag S. Maskey 3256ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_create(kw->kw_essid, &kwh)) 3266ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 3276ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 3286ba597c5SAnurag S. Maskey "could not create known wlan: %s", kw->kw_essid, 3296ba597c5SAnurag S. Maskey nwam_strerror(err)); 3306ba597c5SAnurag S. Maskey continue; 3316ba597c5SAnurag S. Maskey } 3326ba597c5SAnurag S. Maskey 3336ba597c5SAnurag S. Maskey /* priority of this ESSID */ 3346ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64(priority, &priorityval)) 3356ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 3366ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 3376ba597c5SAnurag S. Maskey "could not create priority value: %s", kw->kw_essid, 3386ba597c5SAnurag S. Maskey nwam_strerror(err)); 3396ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 3406ba597c5SAnurag S. Maskey continue; 3416ba597c5SAnurag S. Maskey } 3426ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 3436ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval); 3446ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 3456ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 3466ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 3476ba597c5SAnurag S. Maskey "could not set priority value: %s", kw->kw_essid, 3486ba597c5SAnurag S. Maskey nwam_strerror(err)); 3496ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 3506ba597c5SAnurag S. Maskey continue; 3516ba597c5SAnurag S. Maskey } 3526ba597c5SAnurag S. Maskey 3536ba597c5SAnurag S. Maskey /* loop through kw->kw_bssids and create an array of bssids */ 3546ba597c5SAnurag S. Maskey bssids = calloc(kw->kw_num_bssids, sizeof (char *)); 3556ba597c5SAnurag S. Maskey if (bssids == NULL) { 3566ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 3576ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 3586ba597c5SAnurag S. Maskey "could not calloc for bssids: %m", kw->kw_essid); 3596ba597c5SAnurag S. Maskey continue; 3606ba597c5SAnurag S. Maskey } 3616ba597c5SAnurag S. Maskey for (b = (bssid_t *)kw->kw_bssids.q_forw, i = 0; 3626ba597c5SAnurag S. Maskey b != (bssid_t *)&kw->kw_bssids; 3636ba597c5SAnurag S. Maskey b = (bssid_t *)b->bssid_links.q_forw, i++) { 3646ba597c5SAnurag S. Maskey bssids[i] = strdup(b->bssid); 3656ba597c5SAnurag S. Maskey } 3666ba597c5SAnurag S. Maskey 3676ba597c5SAnurag S. Maskey /* BSSIDs for this ESSID */ 3686ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string_array(bssids, 3696ba597c5SAnurag S. Maskey kw->kw_num_bssids, &bssidsval)) != NWAM_SUCCESS) { 3706ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 3716ba597c5SAnurag S. Maskey "could not create bssids value: %s", kw->kw_essid, 3726ba597c5SAnurag S. Maskey nwam_strerror(err)); 3736ba597c5SAnurag S. Maskey for (i = 0; i < kw->kw_num_bssids; i++) 3746ba597c5SAnurag S. Maskey free(bssids[i]); 3756ba597c5SAnurag S. Maskey free(bssids); 3766ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 3776ba597c5SAnurag S. Maskey continue; 3786ba597c5SAnurag S. Maskey } 3796ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 3806ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS, bssidsval); 3816ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 3826ba597c5SAnurag S. Maskey for (i = 0; i < kw->kw_num_bssids; i++) 3836ba597c5SAnurag S. Maskey free(bssids[i]); 3846ba597c5SAnurag S. Maskey free(bssids); 3856ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 3866ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 3876ba597c5SAnurag S. Maskey "could not set bssids: %s", kw->kw_essid, 3886ba597c5SAnurag S. Maskey nwam_strerror(err)); 3896ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 3906ba597c5SAnurag S. Maskey continue; 3916ba597c5SAnurag S. Maskey } 3926ba597c5SAnurag S. Maskey 3936ba597c5SAnurag S. Maskey /* 3946ba597c5SAnurag S. Maskey * Retrieve last key matching ESSID prefix if any, and set 3956ba597c5SAnurag S. Maskey * the retrieved key name and security mode. 3966ba597c5SAnurag S. Maskey */ 3976ba597c5SAnurag S. Maskey nwamd_set_key_name(kw->kw_essid, NULL, nsa.nsa_essid_prefix, 3986ba597c5SAnurag S. Maskey sizeof (nsa.nsa_essid_prefix)); 3996ba597c5SAnurag S. Maskey nsa.nsa_key = NULL; 4006ba597c5SAnurag S. Maskey nsa.nsa_secmode = DLADM_WLAN_SECMODE_NONE; 4016ba597c5SAnurag S. Maskey (void) dladm_walk_secobj(dld_handle, &nsa, 4026ba597c5SAnurag S. Maskey find_secobj_matching_prefix, DLADM_OPT_PERSIST); 4036ba597c5SAnurag S. Maskey if (nsa.nsa_key != NULL) { 4046ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string(nsa.nsa_keyname, 4056ba597c5SAnurag S. Maskey &keynameval)) == NWAM_SUCCESS) { 4066ba597c5SAnurag S. Maskey (void) nwam_known_wlan_set_prop_value(kwh, 4076ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_KEYNAME, keynameval); 4086ba597c5SAnurag S. Maskey } 4096ba597c5SAnurag S. Maskey free(nsa.nsa_key); 4106ba597c5SAnurag S. Maskey nwam_value_free(keynameval); 4116ba597c5SAnurag S. Maskey } 4126ba597c5SAnurag S. Maskey 4136ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64(nsa.nsa_secmode, 4146ba597c5SAnurag S. Maskey &secmodeval)) != NWAM_SUCCESS || 4156ba597c5SAnurag S. Maskey (err = nwam_known_wlan_set_prop_value(kwh, 4166ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_SECURITY_MODE, secmodeval)) 4176ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 4186ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 4196ba597c5SAnurag S. Maskey "could not set security mode: %s", 4206ba597c5SAnurag S. Maskey kw->kw_essid, nwam_strerror(err)); 4216ba597c5SAnurag S. Maskey nwam_value_free(secmodeval); 4226ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 4236ba597c5SAnurag S. Maskey continue; 4246ba597c5SAnurag S. Maskey } 4256ba597c5SAnurag S. Maskey 4266ba597c5SAnurag S. Maskey /* commit, no collision checking by libnwam */ 4276ba597c5SAnurag S. Maskey err = nwam_known_wlan_commit(kwh, 4286ba597c5SAnurag S. Maskey NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK); 4296ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 4306ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 4316ba597c5SAnurag S. Maskey nlog(LOG_ERR, "upgrade wlan %s: " 4326ba597c5SAnurag S. Maskey "could not commit wlan: %s", kw->kw_essid, 4336ba597c5SAnurag S. Maskey nwam_strerror(err)); 4346ba597c5SAnurag S. Maskey } 4356ba597c5SAnurag S. Maskey /* next ... */ 4366ba597c5SAnurag S. Maskey } 4376ba597c5SAnurag S. Maskey 4386ba597c5SAnurag S. Maskey kw_list_free(); 4396ba597c5SAnurag S. Maskey } 4406ba597c5SAnurag S. Maskey 4416ba597c5SAnurag S. Maskey nwam_error_t 4426ba597c5SAnurag S. Maskey known_wlan_get_keyname(const char *essid, char *name) 4436ba597c5SAnurag S. Maskey { 4446ba597c5SAnurag S. Maskey nwam_known_wlan_handle_t kwh = NULL; 4456ba597c5SAnurag S. Maskey nwam_value_t keynameval = NULL; 4466ba597c5SAnurag S. Maskey char *keyname; 4476ba597c5SAnurag S. Maskey nwam_error_t err; 4486ba597c5SAnurag S. Maskey 4496ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_read(essid, 0, &kwh)) != NWAM_SUCCESS) 4506ba597c5SAnurag S. Maskey return (err); 4516ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_get_prop_value(kwh, 4526ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_KEYNAME, &keynameval)) == NWAM_SUCCESS && 4536ba597c5SAnurag S. Maskey (err = nwam_value_get_string(keynameval, &keyname)) 4546ba597c5SAnurag S. Maskey == NWAM_SUCCESS) { 4556ba597c5SAnurag S. Maskey (void) strlcpy(name, keyname, NWAM_MAX_VALUE_LEN); 4566ba597c5SAnurag S. Maskey } 4576ba597c5SAnurag S. Maskey if (keynameval != NULL) 4586ba597c5SAnurag S. Maskey nwam_value_free(keynameval); 4596ba597c5SAnurag S. Maskey 4606ba597c5SAnurag S. Maskey if (kwh != NULL) 4616ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 4626ba597c5SAnurag S. Maskey 4636ba597c5SAnurag S. Maskey return (err); 4646ba597c5SAnurag S. Maskey } 4656ba597c5SAnurag S. Maskey 4666ba597c5SAnurag S. Maskey /* Performs a scan on a wifi link NCU */ 4676ba597c5SAnurag S. Maskey /* ARGSUSED */ 4686ba597c5SAnurag S. Maskey static int 4696ba597c5SAnurag S. Maskey nwamd_ncu_known_wlan_committed(nwamd_object_t object, void *data) 4706ba597c5SAnurag S. Maskey { 4716ba597c5SAnurag S. Maskey nwamd_ncu_t *ncu_data = object->nwamd_object_data; 4726ba597c5SAnurag S. Maskey 4736ba597c5SAnurag S. Maskey if (ncu_data->ncu_type != NWAM_NCU_TYPE_LINK) 4746ba597c5SAnurag S. Maskey return (0); 4756ba597c5SAnurag S. Maskey 4766ba597c5SAnurag S. Maskey /* network selection will be done only if possible */ 477*f6da83d4SAnurag S. Maskey if (ncu_data->ncu_link.nwamd_link_media == DL_WIFI) 4786ba597c5SAnurag S. Maskey (void) nwamd_wlan_scan(ncu_data->ncu_name); 4796ba597c5SAnurag S. Maskey return (0); 4806ba597c5SAnurag S. Maskey } 4816ba597c5SAnurag S. Maskey 4826ba597c5SAnurag S. Maskey /* Handle known WLAN initialization/refresh event */ 4836ba597c5SAnurag S. Maskey /* ARGSUSED */ 4846ba597c5SAnurag S. Maskey void 4856ba597c5SAnurag S. Maskey nwamd_known_wlan_handle_init_event(nwamd_event_t known_wlan_event) 4866ba597c5SAnurag S. Maskey { 4876ba597c5SAnurag S. Maskey /* 4886ba597c5SAnurag S. Maskey * Since the Known WLAN list has changed, do a rescan so that the 4896ba597c5SAnurag S. Maskey * best network is selected. 4906ba597c5SAnurag S. Maskey */ 4916ba597c5SAnurag S. Maskey (void) nwamd_walk_objects(NWAM_OBJECT_TYPE_NCU, 4926ba597c5SAnurag S. Maskey nwamd_ncu_known_wlan_committed, NULL); 4936ba597c5SAnurag S. Maskey } 4946ba597c5SAnurag S. Maskey 4956ba597c5SAnurag S. Maskey void 4966ba597c5SAnurag S. Maskey nwamd_known_wlan_handle_action_event(nwamd_event_t known_wlan_event) 4976ba597c5SAnurag S. Maskey { 4986ba597c5SAnurag S. Maskey switch (known_wlan_event->event_msg->nwe_data.nwe_object_action. 4996ba597c5SAnurag S. Maskey nwe_action) { 5006ba597c5SAnurag S. Maskey case NWAM_ACTION_ADD: 5016ba597c5SAnurag S. Maskey case NWAM_ACTION_REFRESH: 5026ba597c5SAnurag S. Maskey nwamd_known_wlan_handle_init_event(known_wlan_event); 5036ba597c5SAnurag S. Maskey break; 5046ba597c5SAnurag S. Maskey case NWAM_ACTION_DESTROY: 5056ba597c5SAnurag S. Maskey /* Nothing needs to be done for destroy */ 5066ba597c5SAnurag S. Maskey break; 5076ba597c5SAnurag S. Maskey /* all other events are invalid for known WLANs */ 5086ba597c5SAnurag S. Maskey case NWAM_ACTION_ENABLE: 5096ba597c5SAnurag S. Maskey case NWAM_ACTION_DISABLE: 5106ba597c5SAnurag S. Maskey default: 5116ba597c5SAnurag S. Maskey nlog(LOG_INFO, "nwam_known_wlan_handle_action_event: " 5126ba597c5SAnurag S. Maskey "unexpected action"); 5136ba597c5SAnurag S. Maskey break; 5146ba597c5SAnurag S. Maskey } 5156ba597c5SAnurag S. Maskey } 5166ba597c5SAnurag S. Maskey 5176ba597c5SAnurag S. Maskey int 5186ba597c5SAnurag S. Maskey nwamd_known_wlan_action(const char *known_wlan, nwam_action_t action) 5196ba597c5SAnurag S. Maskey { 5206ba597c5SAnurag S. Maskey nwamd_event_t known_wlan_event = nwamd_event_init_object_action 5216ba597c5SAnurag S. Maskey (NWAM_OBJECT_TYPE_KNOWN_WLAN, known_wlan, NULL, action); 5226ba597c5SAnurag S. Maskey if (known_wlan_event == NULL) 5236ba597c5SAnurag S. Maskey return (1); 5246ba597c5SAnurag S. Maskey nwamd_event_enqueue(known_wlan_event); 5256ba597c5SAnurag S. Maskey return (0); 5266ba597c5SAnurag S. Maskey } 527