1*6ba597c5SAnurag S. Maskey /* 2*6ba597c5SAnurag S. Maskey * CDDL HEADER START 3*6ba597c5SAnurag S. Maskey * 4*6ba597c5SAnurag S. Maskey * The contents of this file are subject to the terms of the 5*6ba597c5SAnurag S. Maskey * Common Development and Distribution License (the "License"). 6*6ba597c5SAnurag S. Maskey * You may not use this file except in compliance with the License. 7*6ba597c5SAnurag S. Maskey * 8*6ba597c5SAnurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6ba597c5SAnurag S. Maskey * or http://www.opensolaris.org/os/licensing. 10*6ba597c5SAnurag S. Maskey * See the License for the specific language governing permissions 11*6ba597c5SAnurag S. Maskey * and limitations under the License. 12*6ba597c5SAnurag S. Maskey * 13*6ba597c5SAnurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each 14*6ba597c5SAnurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6ba597c5SAnurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the 16*6ba597c5SAnurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying 17*6ba597c5SAnurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner] 18*6ba597c5SAnurag S. Maskey * 19*6ba597c5SAnurag S. Maskey * CDDL HEADER END 20*6ba597c5SAnurag S. Maskey */ 21*6ba597c5SAnurag S. Maskey 22*6ba597c5SAnurag S. Maskey /* 23*6ba597c5SAnurag S. Maskey * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24*6ba597c5SAnurag S. Maskey * Use is subject to license terms. 25*6ba597c5SAnurag S. Maskey */ 26*6ba597c5SAnurag S. Maskey 27*6ba597c5SAnurag S. Maskey #include <assert.h> 28*6ba597c5SAnurag S. Maskey #include <ctype.h> 29*6ba597c5SAnurag S. Maskey #include <sys/param.h> 30*6ba597c5SAnurag S. Maskey #include <sys/types.h> 31*6ba597c5SAnurag S. Maskey #include <sys/stat.h> 32*6ba597c5SAnurag S. Maskey #include <stdio.h> 33*6ba597c5SAnurag S. Maskey #include <stdlib.h> 34*6ba597c5SAnurag S. Maskey #include <strings.h> 35*6ba597c5SAnurag S. Maskey #include <unistd.h> 36*6ba597c5SAnurag S. Maskey #include <libdllink.h> 37*6ba597c5SAnurag S. Maskey #include <libdlwlan.h> 38*6ba597c5SAnurag S. Maskey 39*6ba597c5SAnurag S. Maskey #include "libnwam_impl.h" 40*6ba597c5SAnurag S. Maskey #include <libnwam_priv.h> 41*6ba597c5SAnurag S. Maskey #include <libnwam.h> 42*6ba597c5SAnurag S. Maskey 43*6ba597c5SAnurag S. Maskey /* 44*6ba597c5SAnurag S. Maskey * Functions to support creating, modifying and destroying 45*6ba597c5SAnurag S. Maskey * known WLAN objects. These represent the WiFi connection history, 46*6ba597c5SAnurag S. Maskey * and are used by nwamd to identify and connect to known WLANs in 47*6ba597c5SAnurag S. Maskey * scan results. 48*6ba597c5SAnurag S. Maskey */ 49*6ba597c5SAnurag S. Maskey 50*6ba597c5SAnurag S. Maskey static nwam_error_t valid_keyname(nwam_value_t); 51*6ba597c5SAnurag S. Maskey static nwam_error_t valid_keyslot(nwam_value_t); 52*6ba597c5SAnurag S. Maskey static nwam_error_t valid_secmode(nwam_value_t); 53*6ba597c5SAnurag S. Maskey 54*6ba597c5SAnurag S. Maskey struct nwam_prop_table_entry known_wlan_prop_table_entries[] = { 55*6ba597c5SAnurag S. Maskey {NWAM_KNOWN_WLAN_PROP_PRIORITY, NWAM_VALUE_TYPE_UINT64, B_FALSE, 56*6ba597c5SAnurag S. Maskey 1, 1, nwam_valid_uint64, 57*6ba597c5SAnurag S. Maskey "specifies priority of known WLAN - lower values are prioritized", 58*6ba597c5SAnurag S. Maskey NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 59*6ba597c5SAnurag S. Maskey {NWAM_KNOWN_WLAN_PROP_BSSIDS, NWAM_VALUE_TYPE_STRING, B_FALSE, 60*6ba597c5SAnurag S. Maskey 0, NWAM_MAX_NUM_VALUES, nwam_valid_mac_addr, 61*6ba597c5SAnurag S. Maskey "specifies BSSID(s) (of the form aa:bb:cc:dd:ee:ff) associated " 62*6ba597c5SAnurag S. Maskey "with known WLAN", 63*6ba597c5SAnurag S. Maskey NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 64*6ba597c5SAnurag S. Maskey {NWAM_KNOWN_WLAN_PROP_KEYNAME, NWAM_VALUE_TYPE_STRING, B_FALSE, 65*6ba597c5SAnurag S. Maskey 0, 1, valid_keyname, 66*6ba597c5SAnurag S. Maskey "specifies security key name used with known WLAN", 67*6ba597c5SAnurag S. Maskey NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 68*6ba597c5SAnurag S. Maskey {NWAM_KNOWN_WLAN_PROP_KEYSLOT, NWAM_VALUE_TYPE_UINT64, B_FALSE, 69*6ba597c5SAnurag S. Maskey 0, 1, valid_keyslot, 70*6ba597c5SAnurag S. Maskey "specifies key slot [1-4] for security key used with known WLAN", 71*6ba597c5SAnurag S. Maskey NWAM_TYPE_ANY, NWAM_CLASS_ANY}, 72*6ba597c5SAnurag S. Maskey {NWAM_KNOWN_WLAN_PROP_SECURITY_MODE, NWAM_VALUE_TYPE_UINT64, B_FALSE, 73*6ba597c5SAnurag S. Maskey 0, 1, valid_secmode, 74*6ba597c5SAnurag S. Maskey "specifies security mode used for known WLAN", 75*6ba597c5SAnurag S. Maskey NWAM_TYPE_ANY, NWAM_CLASS_ANY} 76*6ba597c5SAnurag S. Maskey }; 77*6ba597c5SAnurag S. Maskey 78*6ba597c5SAnurag S. Maskey #define NWAM_NUM_KNOWN_WLAN_PROPS \ 79*6ba597c5SAnurag S. Maskey (sizeof (known_wlan_prop_table_entries) / \ 80*6ba597c5SAnurag S. Maskey sizeof (*known_wlan_prop_table_entries)) 81*6ba597c5SAnurag S. Maskey 82*6ba597c5SAnurag S. Maskey struct nwam_prop_table known_wlan_prop_table = 83*6ba597c5SAnurag S. Maskey { NWAM_NUM_KNOWN_WLAN_PROPS, known_wlan_prop_table_entries }; 84*6ba597c5SAnurag S. Maskey 85*6ba597c5SAnurag S. Maskey nwam_error_t 86*6ba597c5SAnurag S. Maskey nwam_known_wlan_read(const char *name, uint64_t flags, 87*6ba597c5SAnurag S. Maskey nwam_known_wlan_handle_t *kwhp) 88*6ba597c5SAnurag S. Maskey { 89*6ba597c5SAnurag S. Maskey return (nwam_read(NWAM_OBJECT_TYPE_KNOWN_WLAN, 90*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_CONF_FILE, name, flags, kwhp)); 91*6ba597c5SAnurag S. Maskey } 92*6ba597c5SAnurag S. Maskey 93*6ba597c5SAnurag S. Maskey nwam_error_t 94*6ba597c5SAnurag S. Maskey nwam_known_wlan_create(const char *name, nwam_known_wlan_handle_t *kwhp) 95*6ba597c5SAnurag S. Maskey { 96*6ba597c5SAnurag S. Maskey nwam_error_t err; 97*6ba597c5SAnurag S. Maskey nwam_value_t priorityval = NULL; 98*6ba597c5SAnurag S. Maskey 99*6ba597c5SAnurag S. Maskey assert(kwhp != NULL && name != NULL); 100*6ba597c5SAnurag S. Maskey 101*6ba597c5SAnurag S. Maskey if ((err = nwam_create(NWAM_OBJECT_TYPE_KNOWN_WLAN, 102*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_CONF_FILE, name, kwhp)) != NWAM_SUCCESS) 103*6ba597c5SAnurag S. Maskey return (err); 104*6ba597c5SAnurag S. Maskey 105*6ba597c5SAnurag S. Maskey /* 106*6ba597c5SAnurag S. Maskey * Create new object list for known WLAN. The initial priority is 107*6ba597c5SAnurag S. Maskey * also set. 108*6ba597c5SAnurag S. Maskey */ 109*6ba597c5SAnurag S. Maskey if ((err = nwam_alloc_object_list(&((*kwhp)->nwh_data))) 110*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 111*6ba597c5SAnurag S. Maskey goto finish; 112*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64(0, &priorityval)) != NWAM_SUCCESS) 113*6ba597c5SAnurag S. Maskey goto finish; 114*6ba597c5SAnurag S. Maskey err = nwam_set_prop_value((*kwhp)->nwh_data, 115*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval); 116*6ba597c5SAnurag S. Maskey 117*6ba597c5SAnurag S. Maskey finish: 118*6ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 119*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 120*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(*kwhp); 121*6ba597c5SAnurag S. Maskey *kwhp = NULL; 122*6ba597c5SAnurag S. Maskey } 123*6ba597c5SAnurag S. Maskey return (err); 124*6ba597c5SAnurag S. Maskey } 125*6ba597c5SAnurag S. Maskey 126*6ba597c5SAnurag S. Maskey nwam_error_t 127*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_name(nwam_known_wlan_handle_t kwh, char **namep) 128*6ba597c5SAnurag S. Maskey { 129*6ba597c5SAnurag S. Maskey return (nwam_get_name(kwh, namep)); 130*6ba597c5SAnurag S. Maskey } 131*6ba597c5SAnurag S. Maskey 132*6ba597c5SAnurag S. Maskey nwam_error_t 133*6ba597c5SAnurag S. Maskey nwam_known_wlan_set_name(nwam_known_wlan_handle_t kwh, const char *name) 134*6ba597c5SAnurag S. Maskey { 135*6ba597c5SAnurag S. Maskey return (nwam_set_name(kwh, name)); 136*6ba597c5SAnurag S. Maskey } 137*6ba597c5SAnurag S. Maskey 138*6ba597c5SAnurag S. Maskey boolean_t 139*6ba597c5SAnurag S. Maskey nwam_known_wlan_can_set_name(nwam_known_wlan_handle_t kwh) 140*6ba597c5SAnurag S. Maskey { 141*6ba597c5SAnurag S. Maskey return (!kwh->nwh_committed); 142*6ba597c5SAnurag S. Maskey } 143*6ba597c5SAnurag S. Maskey 144*6ba597c5SAnurag S. Maskey /* 145*6ba597c5SAnurag S. Maskey * Used to store wlan names/priorities for prioritized walk. 146*6ba597c5SAnurag S. Maskey */ 147*6ba597c5SAnurag S. Maskey struct nwam_wlan_info { 148*6ba597c5SAnurag S. Maskey char *wlan_name; 149*6ba597c5SAnurag S. Maskey uint64_t wlan_priority; 150*6ba597c5SAnurag S. Maskey boolean_t wlan_walked; 151*6ba597c5SAnurag S. Maskey }; 152*6ba597c5SAnurag S. Maskey 153*6ba597c5SAnurag S. Maskey struct nwam_wlan_info_list { 154*6ba597c5SAnurag S. Maskey struct nwam_wlan_info **list; 155*6ba597c5SAnurag S. Maskey uint_t num_wlans; 156*6ba597c5SAnurag S. Maskey }; 157*6ba597c5SAnurag S. Maskey 158*6ba597c5SAnurag S. Maskey /* 159*6ba597c5SAnurag S. Maskey * Used to read in each known WLAN name/priority. 160*6ba597c5SAnurag S. Maskey */ 161*6ba597c5SAnurag S. Maskey static int 162*6ba597c5SAnurag S. Maskey get_wlans_cb(nwam_known_wlan_handle_t kwh, void *data) 163*6ba597c5SAnurag S. Maskey { 164*6ba597c5SAnurag S. Maskey struct nwam_wlan_info_list *wil = data; 165*6ba597c5SAnurag S. Maskey struct nwam_wlan_info **list = wil->list; 166*6ba597c5SAnurag S. Maskey struct nwam_wlan_info **newlist = NULL; 167*6ba597c5SAnurag S. Maskey nwam_error_t err; 168*6ba597c5SAnurag S. Maskey nwam_value_t priorityval = NULL; 169*6ba597c5SAnurag S. Maskey uint_t num_wlans = wil->num_wlans; 170*6ba597c5SAnurag S. Maskey 171*6ba597c5SAnurag S. Maskey /* Reallocate WLAN list and allocate new info list element. */ 172*6ba597c5SAnurag S. Maskey if ((newlist = realloc(list, 173*6ba597c5SAnurag S. Maskey sizeof (struct nwam_wlan_info *) * ++num_wlans)) == NULL || 174*6ba597c5SAnurag S. Maskey (newlist[num_wlans - 1] = calloc(1, 175*6ba597c5SAnurag S. Maskey sizeof (struct nwam_wlan_info))) == NULL) { 176*6ba597c5SAnurag S. Maskey if (newlist != NULL) 177*6ba597c5SAnurag S. Maskey free(newlist); 178*6ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY); 179*6ba597c5SAnurag S. Maskey } 180*6ba597c5SAnurag S. Maskey 181*6ba597c5SAnurag S. Maskey /* Update list since realloc() may have relocated it */ 182*6ba597c5SAnurag S. Maskey wil->list = newlist; 183*6ba597c5SAnurag S. Maskey 184*6ba597c5SAnurag S. Maskey /* Retrieve name/priority */ 185*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_get_name(kwh, 186*6ba597c5SAnurag S. Maskey &((newlist[num_wlans - 1])->wlan_name))) != NWAM_SUCCESS || 187*6ba597c5SAnurag S. Maskey (err = nwam_known_wlan_get_prop_value(kwh, 188*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_PRIORITY, &priorityval)) != NWAM_SUCCESS || 189*6ba597c5SAnurag S. Maskey (err = nwam_value_get_uint64(priorityval, 190*6ba597c5SAnurag S. Maskey &((newlist[num_wlans - 1])->wlan_priority))) != NWAM_SUCCESS) { 191*6ba597c5SAnurag S. Maskey free(newlist[num_wlans - 1]->wlan_name); 192*6ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 193*6ba597c5SAnurag S. Maskey free(newlist[num_wlans - 1]); 194*6ba597c5SAnurag S. Maskey return (err); 195*6ba597c5SAnurag S. Maskey } 196*6ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 197*6ba597c5SAnurag S. Maskey 198*6ba597c5SAnurag S. Maskey (newlist[num_wlans - 1])->wlan_walked = B_FALSE; 199*6ba597c5SAnurag S. Maskey 200*6ba597c5SAnurag S. Maskey wil->num_wlans = num_wlans; 201*6ba597c5SAnurag S. Maskey 202*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 203*6ba597c5SAnurag S. Maskey } 204*6ba597c5SAnurag S. Maskey 205*6ba597c5SAnurag S. Maskey /* 206*6ba597c5SAnurag S. Maskey * Some recursion is required here, since if _WALK_PRIORITY_ORDER is specified, 207*6ba597c5SAnurag S. Maskey * we need to first walk the list of known WLANs to retrieve names 208*6ba597c5SAnurag S. Maskey * and priorities, then utilize that list to carry out an in-order walk. 209*6ba597c5SAnurag S. Maskey */ 210*6ba597c5SAnurag S. Maskey nwam_error_t 211*6ba597c5SAnurag S. Maskey nwam_walk_known_wlans(int(*cb)(nwam_known_wlan_handle_t, void *), void *data, 212*6ba597c5SAnurag S. Maskey uint64_t flags, int *retp) 213*6ba597c5SAnurag S. Maskey { 214*6ba597c5SAnurag S. Maskey nwam_known_wlan_handle_t kwh; 215*6ba597c5SAnurag S. Maskey nwam_error_t err; 216*6ba597c5SAnurag S. Maskey int ret = 0; 217*6ba597c5SAnurag S. Maskey 218*6ba597c5SAnurag S. Maskey assert(cb != NULL); 219*6ba597c5SAnurag S. Maskey 220*6ba597c5SAnurag S. Maskey if ((err = nwam_valid_flags(flags, 221*6ba597c5SAnurag S. Maskey NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER | NWAM_FLAG_BLOCKING)) 222*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 223*6ba597c5SAnurag S. Maskey return (err); 224*6ba597c5SAnurag S. Maskey 225*6ba597c5SAnurag S. Maskey if ((flags & NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER) != 0) { 226*6ba597c5SAnurag S. Maskey struct nwam_wlan_info_list wil = { NULL, 0}; 227*6ba597c5SAnurag S. Maskey uint64_t iflags = flags &~ 228*6ba597c5SAnurag S. Maskey NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER; 229*6ba597c5SAnurag S. Maskey uint64_t minpriority; 230*6ba597c5SAnurag S. Maskey int errval, i, j, minindex; 231*6ba597c5SAnurag S. Maskey 232*6ba597c5SAnurag S. Maskey if (nwam_walk_known_wlans(get_wlans_cb, &wil, iflags, &errval) 233*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 234*6ba597c5SAnurag S. Maskey err = (nwam_error_t)errval; 235*6ba597c5SAnurag S. Maskey goto done; 236*6ba597c5SAnurag S. Maskey } 237*6ba597c5SAnurag S. Maskey 238*6ba597c5SAnurag S. Maskey err = NWAM_SUCCESS; 239*6ba597c5SAnurag S. Maskey 240*6ba597c5SAnurag S. Maskey for (i = 0; i < wil.num_wlans; i++) { 241*6ba597c5SAnurag S. Maskey /* Find lowest priority value not walked so far. */ 242*6ba597c5SAnurag S. Maskey minpriority = (uint64_t)-1; 243*6ba597c5SAnurag S. Maskey for (j = 0; j < wil.num_wlans; j++) { 244*6ba597c5SAnurag S. Maskey if (wil.list[j]->wlan_priority < minpriority && 245*6ba597c5SAnurag S. Maskey !(wil.list[j]->wlan_walked)) { 246*6ba597c5SAnurag S. Maskey minpriority = 247*6ba597c5SAnurag S. Maskey wil.list[j]->wlan_priority; 248*6ba597c5SAnurag S. Maskey minindex = j; 249*6ba597c5SAnurag S. Maskey } 250*6ba597c5SAnurag S. Maskey } 251*6ba597c5SAnurag S. Maskey wil.list[minindex]->wlan_walked = B_TRUE; 252*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_read 253*6ba597c5SAnurag S. Maskey (wil.list[minindex]->wlan_name, 254*6ba597c5SAnurag S. Maskey iflags, &kwh)) != NWAM_SUCCESS) { 255*6ba597c5SAnurag S. Maskey goto done; 256*6ba597c5SAnurag S. Maskey } 257*6ba597c5SAnurag S. Maskey ret = cb(kwh, data); 258*6ba597c5SAnurag S. Maskey if (ret != 0) { 259*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 260*6ba597c5SAnurag S. Maskey err = NWAM_WALK_HALTED; 261*6ba597c5SAnurag S. Maskey goto done; 262*6ba597c5SAnurag S. Maskey } 263*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 264*6ba597c5SAnurag S. Maskey } 265*6ba597c5SAnurag S. Maskey done: 266*6ba597c5SAnurag S. Maskey if (wil.list != NULL) { 267*6ba597c5SAnurag S. Maskey for (j = 0; j < wil.num_wlans; j++) { 268*6ba597c5SAnurag S. Maskey free(wil.list[j]->wlan_name); 269*6ba597c5SAnurag S. Maskey free(wil.list[j]); 270*6ba597c5SAnurag S. Maskey } 271*6ba597c5SAnurag S. Maskey free(wil.list); 272*6ba597c5SAnurag S. Maskey } 273*6ba597c5SAnurag S. Maskey if (retp != NULL) 274*6ba597c5SAnurag S. Maskey *retp = ret; 275*6ba597c5SAnurag S. Maskey return (err); 276*6ba597c5SAnurag S. Maskey } 277*6ba597c5SAnurag S. Maskey 278*6ba597c5SAnurag S. Maskey return (nwam_walk(NWAM_OBJECT_TYPE_KNOWN_WLAN, 279*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_CONF_FILE, cb, data, flags, retp, NULL)); 280*6ba597c5SAnurag S. Maskey } 281*6ba597c5SAnurag S. Maskey 282*6ba597c5SAnurag S. Maskey void 283*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(nwam_known_wlan_handle_t kwh) 284*6ba597c5SAnurag S. Maskey { 285*6ba597c5SAnurag S. Maskey nwam_free(kwh); 286*6ba597c5SAnurag S. Maskey } 287*6ba597c5SAnurag S. Maskey 288*6ba597c5SAnurag S. Maskey nwam_error_t 289*6ba597c5SAnurag S. Maskey nwam_known_wlan_copy(nwam_known_wlan_handle_t oldkwh, const char *newname, 290*6ba597c5SAnurag S. Maskey nwam_known_wlan_handle_t *newkwhp) 291*6ba597c5SAnurag S. Maskey { 292*6ba597c5SAnurag S. Maskey return (nwam_copy(NWAM_KNOWN_WLAN_CONF_FILE, oldkwh, newname, newkwhp)); 293*6ba597c5SAnurag S. Maskey } 294*6ba597c5SAnurag S. Maskey 295*6ba597c5SAnurag S. Maskey nwam_error_t 296*6ba597c5SAnurag S. Maskey nwam_known_wlan_delete_prop(nwam_known_wlan_handle_t kwh, const char *propname) 297*6ba597c5SAnurag S. Maskey { 298*6ba597c5SAnurag S. Maskey nwam_error_t err; 299*6ba597c5SAnurag S. Maskey void *olddata; 300*6ba597c5SAnurag S. Maskey 301*6ba597c5SAnurag S. Maskey assert(kwh != NULL && propname != NULL); 302*6ba597c5SAnurag S. Maskey 303*6ba597c5SAnurag S. Maskey /* 304*6ba597c5SAnurag S. Maskey * Duplicate data, remove property and validate. If validation 305*6ba597c5SAnurag S. Maskey * fails, revert to data duplicated prior to remove. 306*6ba597c5SAnurag S. Maskey */ 307*6ba597c5SAnurag S. Maskey if ((err = nwam_dup_object_list(kwh->nwh_data, &olddata)) 308*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 309*6ba597c5SAnurag S. Maskey return (err); 310*6ba597c5SAnurag S. Maskey if ((err = nwam_delete_prop(kwh->nwh_data, propname)) != NWAM_SUCCESS) { 311*6ba597c5SAnurag S. Maskey nwam_free_object_list(kwh->nwh_data); 312*6ba597c5SAnurag S. Maskey kwh->nwh_data = olddata; 313*6ba597c5SAnurag S. Maskey return (err); 314*6ba597c5SAnurag S. Maskey } 315*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_validate(kwh, NULL)) != NWAM_SUCCESS) { 316*6ba597c5SAnurag S. Maskey nwam_free_object_list(kwh->nwh_data); 317*6ba597c5SAnurag S. Maskey kwh->nwh_data = olddata; 318*6ba597c5SAnurag S. Maskey return (err); 319*6ba597c5SAnurag S. Maskey } 320*6ba597c5SAnurag S. Maskey nwam_free_object_list(olddata); 321*6ba597c5SAnurag S. Maskey 322*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 323*6ba597c5SAnurag S. Maskey } 324*6ba597c5SAnurag S. Maskey 325*6ba597c5SAnurag S. Maskey nwam_error_t 326*6ba597c5SAnurag S. Maskey nwam_known_wlan_set_prop_value(nwam_known_wlan_handle_t kwh, 327*6ba597c5SAnurag S. Maskey const char *propname, nwam_value_t value) 328*6ba597c5SAnurag S. Maskey { 329*6ba597c5SAnurag S. Maskey nwam_error_t err; 330*6ba597c5SAnurag S. Maskey 331*6ba597c5SAnurag S. Maskey assert(kwh != NULL && propname != NULL && value != NULL); 332*6ba597c5SAnurag S. Maskey 333*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_validate_prop(kwh, propname, value)) 334*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) 335*6ba597c5SAnurag S. Maskey return (err); 336*6ba597c5SAnurag S. Maskey 337*6ba597c5SAnurag S. Maskey return (nwam_set_prop_value(kwh->nwh_data, propname, value)); 338*6ba597c5SAnurag S. Maskey } 339*6ba597c5SAnurag S. Maskey 340*6ba597c5SAnurag S. Maskey nwam_error_t 341*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_prop_value(nwam_known_wlan_handle_t kwh, 342*6ba597c5SAnurag S. Maskey const char *propname, nwam_value_t *valuep) 343*6ba597c5SAnurag S. Maskey { 344*6ba597c5SAnurag S. Maskey return (nwam_get_prop_value(kwh->nwh_data, propname, valuep)); 345*6ba597c5SAnurag S. Maskey } 346*6ba597c5SAnurag S. Maskey 347*6ba597c5SAnurag S. Maskey nwam_error_t 348*6ba597c5SAnurag S. Maskey nwam_known_wlan_walk_props(nwam_known_wlan_handle_t kwh, 349*6ba597c5SAnurag S. Maskey int (*cb)(const char *, nwam_value_t, void *), 350*6ba597c5SAnurag S. Maskey void *data, uint64_t flags, int *retp) 351*6ba597c5SAnurag S. Maskey { 352*6ba597c5SAnurag S. Maskey return (nwam_walk_props(kwh, cb, data, flags, retp)); 353*6ba597c5SAnurag S. Maskey } 354*6ba597c5SAnurag S. Maskey 355*6ba597c5SAnurag S. Maskey struct priority_collision_data { 356*6ba597c5SAnurag S. Maskey char *wlan_name; 357*6ba597c5SAnurag S. Maskey uint64_t priority; 358*6ba597c5SAnurag S. Maskey }; 359*6ba597c5SAnurag S. Maskey 360*6ba597c5SAnurag S. Maskey static int 361*6ba597c5SAnurag S. Maskey avoid_priority_collisions_cb(nwam_known_wlan_handle_t kwh, void *data) 362*6ba597c5SAnurag S. Maskey { 363*6ba597c5SAnurag S. Maskey nwam_value_t priorityval; 364*6ba597c5SAnurag S. Maskey nwam_error_t err; 365*6ba597c5SAnurag S. Maskey struct priority_collision_data *pcd = data; 366*6ba597c5SAnurag S. Maskey char *name; 367*6ba597c5SAnurag S. Maskey uint64_t priority; 368*6ba597c5SAnurag S. Maskey 369*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_get_name(kwh, &name); 370*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 371*6ba597c5SAnurag S. Maskey return (err); 372*6ba597c5SAnurag S. Maskey if (strcmp(name, pcd->wlan_name) == 0) { 373*6ba597c5SAnurag S. Maskey /* skip to-be-updated wlan */ 374*6ba597c5SAnurag S. Maskey free(name); 375*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 376*6ba597c5SAnurag S. Maskey } 377*6ba597c5SAnurag S. Maskey free(name); 378*6ba597c5SAnurag S. Maskey 379*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_get_prop_value(kwh, NWAM_KNOWN_WLAN_PROP_PRIORITY, 380*6ba597c5SAnurag S. Maskey &priorityval); 381*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 382*6ba597c5SAnurag S. Maskey return (err); 383*6ba597c5SAnurag S. Maskey err = nwam_value_get_uint64(priorityval, &priority); 384*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 385*6ba597c5SAnurag S. Maskey return (err); 386*6ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 387*6ba597c5SAnurag S. Maskey 388*6ba597c5SAnurag S. Maskey if (priority < pcd->priority) 389*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 390*6ba597c5SAnurag S. Maskey 391*6ba597c5SAnurag S. Maskey if (priority == pcd->priority) { 392*6ba597c5SAnurag S. Maskey /* Two priority values collide. Move this one up. */ 393*6ba597c5SAnurag S. Maskey err = nwam_value_create_uint64(priority + 1, &priorityval); 394*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 395*6ba597c5SAnurag S. Maskey return (err); 396*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 397*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval); 398*6ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 399*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 400*6ba597c5SAnurag S. Maskey return (err); 401*6ba597c5SAnurag S. Maskey } 402*6ba597c5SAnurag S. Maskey /* 403*6ba597c5SAnurag S. Maskey * We are doing a walk, and will continue shifting until 404*6ba597c5SAnurag S. Maskey * we find a gap in the priority numbers; thus no need to 405*6ba597c5SAnurag S. Maskey * do collision checking here. 406*6ba597c5SAnurag S. Maskey */ 407*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_commit(kwh, 408*6ba597c5SAnurag S. Maskey NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK); 409*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 410*6ba597c5SAnurag S. Maskey return (err); 411*6ba597c5SAnurag S. Maskey 412*6ba597c5SAnurag S. Maskey (pcd->priority)++; 413*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 414*6ba597c5SAnurag S. Maskey } 415*6ba597c5SAnurag S. Maskey 416*6ba597c5SAnurag S. Maskey /* 417*6ba597c5SAnurag S. Maskey * Only possiblity left at this point is that we're looking 418*6ba597c5SAnurag S. Maskey * at a priority greater than the last one we wrote, so we've 419*6ba597c5SAnurag S. Maskey * found a gap. We can halt the walk now. 420*6ba597c5SAnurag S. Maskey */ 421*6ba597c5SAnurag S. Maskey return (NWAM_WALK_HALTED); 422*6ba597c5SAnurag S. Maskey } 423*6ba597c5SAnurag S. Maskey 424*6ba597c5SAnurag S. Maskey nwam_error_t 425*6ba597c5SAnurag S. Maskey nwam_known_wlan_commit(nwam_known_wlan_handle_t kwh, uint64_t flags) 426*6ba597c5SAnurag S. Maskey { 427*6ba597c5SAnurag S. Maskey nwam_error_t err; 428*6ba597c5SAnurag S. Maskey nwam_value_t priorityval; 429*6ba597c5SAnurag S. Maskey int ret = 0; 430*6ba597c5SAnurag S. Maskey struct priority_collision_data pcd; 431*6ba597c5SAnurag S. Maskey 432*6ba597c5SAnurag S. Maskey assert(kwh != NULL && kwh->nwh_data != NULL); 433*6ba597c5SAnurag S. Maskey 434*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_validate(kwh, NULL)) != NWAM_SUCCESS) 435*6ba597c5SAnurag S. Maskey return (err); 436*6ba597c5SAnurag S. Maskey 437*6ba597c5SAnurag S. Maskey /* 438*6ba597c5SAnurag S. Maskey * If the NO_COLLISION_CHECK flag is set, no need to check for 439*6ba597c5SAnurag S. Maskey * collision. 440*6ba597c5SAnurag S. Maskey */ 441*6ba597c5SAnurag S. Maskey if (flags & NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK) 442*6ba597c5SAnurag S. Maskey return (nwam_commit(NWAM_KNOWN_WLAN_CONF_FILE, kwh, 443*6ba597c5SAnurag S. Maskey (flags & NWAM_FLAG_GLOBAL_MASK) | 444*6ba597c5SAnurag S. Maskey NWAM_FLAG_ENTITY_KNOWN_WLAN)); 445*6ba597c5SAnurag S. Maskey 446*6ba597c5SAnurag S. Maskey /* 447*6ba597c5SAnurag S. Maskey * We need to do priority checking. Walk the list, looking 448*6ba597c5SAnurag S. Maskey * for the first entry with priority greater than or equal 449*6ba597c5SAnurag S. Maskey * to the entry we're adding. Commit the new one (without 450*6ba597c5SAnurag S. Maskey * doing additional checking), and then increment other 451*6ba597c5SAnurag S. Maskey * entries as needed. 452*6ba597c5SAnurag S. Maskey */ 453*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_get_prop_value(kwh, 454*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_PRIORITY, &priorityval); 455*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 456*6ba597c5SAnurag S. Maskey return (err); 457*6ba597c5SAnurag S. Maskey err = nwam_value_get_uint64(priorityval, &(pcd.priority)); 458*6ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 459*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 460*6ba597c5SAnurag S. Maskey return (err); 461*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_get_name(kwh, &(pcd.wlan_name)); 462*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) 463*6ba597c5SAnurag S. Maskey return (err); 464*6ba597c5SAnurag S. Maskey err = nwam_walk_known_wlans(avoid_priority_collisions_cb, &pcd, 465*6ba597c5SAnurag S. Maskey NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, &ret); 466*6ba597c5SAnurag S. Maskey free(pcd.wlan_name); 467*6ba597c5SAnurag S. Maskey /* 468*6ba597c5SAnurag S. Maskey * a halted walk is okay, it just means we didn't have 469*6ba597c5SAnurag S. Maskey * to walk the entire list to resolve priorities 470*6ba597c5SAnurag S. Maskey */ 471*6ba597c5SAnurag S. Maskey if (ret != NWAM_SUCCESS && ret != NWAM_WALK_HALTED) 472*6ba597c5SAnurag S. Maskey return (ret); 473*6ba597c5SAnurag S. Maskey 474*6ba597c5SAnurag S. Maskey return (nwam_known_wlan_commit(kwh, 475*6ba597c5SAnurag S. Maskey flags | NWAM_FLAG_KNOWN_WLAN_NO_COLLISION_CHECK)); 476*6ba597c5SAnurag S. Maskey } 477*6ba597c5SAnurag S. Maskey 478*6ba597c5SAnurag S. Maskey nwam_error_t 479*6ba597c5SAnurag S. Maskey nwam_known_wlan_destroy(nwam_known_wlan_handle_t kwh, uint64_t flags) 480*6ba597c5SAnurag S. Maskey { 481*6ba597c5SAnurag S. Maskey return (nwam_destroy(NWAM_KNOWN_WLAN_CONF_FILE, kwh, 482*6ba597c5SAnurag S. Maskey flags | NWAM_FLAG_ENTITY_KNOWN_WLAN)); 483*6ba597c5SAnurag S. Maskey } 484*6ba597c5SAnurag S. Maskey 485*6ba597c5SAnurag S. Maskey nwam_error_t 486*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_prop_description(const char *propname, 487*6ba597c5SAnurag S. Maskey const char **descriptionp) 488*6ba597c5SAnurag S. Maskey { 489*6ba597c5SAnurag S. Maskey return (nwam_get_prop_description(known_wlan_prop_table, propname, 490*6ba597c5SAnurag S. Maskey descriptionp)); 491*6ba597c5SAnurag S. Maskey } 492*6ba597c5SAnurag S. Maskey 493*6ba597c5SAnurag S. Maskey /* Property-specific value validation functions should go here. */ 494*6ba597c5SAnurag S. Maskey 495*6ba597c5SAnurag S. Maskey static nwam_error_t 496*6ba597c5SAnurag S. Maskey valid_keyname(nwam_value_t value) 497*6ba597c5SAnurag S. Maskey { 498*6ba597c5SAnurag S. Maskey char *keyname; 499*6ba597c5SAnurag S. Maskey 500*6ba597c5SAnurag S. Maskey if (nwam_value_get_string(value, &keyname) != NWAM_SUCCESS) 501*6ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE); 502*6ba597c5SAnurag S. Maskey 503*6ba597c5SAnurag S. Maskey if (!dladm_valid_secobj_name(keyname)) 504*6ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE); 505*6ba597c5SAnurag S. Maskey 506*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 507*6ba597c5SAnurag S. Maskey } 508*6ba597c5SAnurag S. Maskey 509*6ba597c5SAnurag S. Maskey static nwam_error_t 510*6ba597c5SAnurag S. Maskey valid_keyslot(nwam_value_t value) 511*6ba597c5SAnurag S. Maskey { 512*6ba597c5SAnurag S. Maskey uint64_t keyslot; 513*6ba597c5SAnurag S. Maskey 514*6ba597c5SAnurag S. Maskey if (nwam_value_get_uint64(value, &keyslot) != NWAM_SUCCESS) 515*6ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE); 516*6ba597c5SAnurag S. Maskey 517*6ba597c5SAnurag S. Maskey if (keyslot < 1 || keyslot > 4) 518*6ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE); 519*6ba597c5SAnurag S. Maskey 520*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 521*6ba597c5SAnurag S. Maskey } 522*6ba597c5SAnurag S. Maskey 523*6ba597c5SAnurag S. Maskey static nwam_error_t 524*6ba597c5SAnurag S. Maskey valid_secmode(nwam_value_t value) 525*6ba597c5SAnurag S. Maskey { 526*6ba597c5SAnurag S. Maskey uint64_t secmode; 527*6ba597c5SAnurag S. Maskey 528*6ba597c5SAnurag S. Maskey if (nwam_value_get_uint64(value, &secmode) != NWAM_SUCCESS) 529*6ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE); 530*6ba597c5SAnurag S. Maskey 531*6ba597c5SAnurag S. Maskey if (secmode != DLADM_WLAN_SECMODE_NONE && 532*6ba597c5SAnurag S. Maskey secmode != DLADM_WLAN_SECMODE_WEP && 533*6ba597c5SAnurag S. Maskey secmode != DLADM_WLAN_SECMODE_WPA) 534*6ba597c5SAnurag S. Maskey return (NWAM_ENTITY_INVALID_VALUE); 535*6ba597c5SAnurag S. Maskey 536*6ba597c5SAnurag S. Maskey return (NWAM_SUCCESS); 537*6ba597c5SAnurag S. Maskey } 538*6ba597c5SAnurag S. Maskey 539*6ba597c5SAnurag S. Maskey nwam_error_t 540*6ba597c5SAnurag S. Maskey nwam_known_wlan_validate(nwam_known_wlan_handle_t kwh, const char **errpropp) 541*6ba597c5SAnurag S. Maskey { 542*6ba597c5SAnurag S. Maskey return (nwam_validate(known_wlan_prop_table, kwh, errpropp)); 543*6ba597c5SAnurag S. Maskey } 544*6ba597c5SAnurag S. Maskey 545*6ba597c5SAnurag S. Maskey nwam_error_t 546*6ba597c5SAnurag S. Maskey nwam_known_wlan_validate_prop(nwam_known_wlan_handle_t kwh, 547*6ba597c5SAnurag S. Maskey const char *propname, nwam_value_t value) 548*6ba597c5SAnurag S. Maskey { 549*6ba597c5SAnurag S. Maskey return (nwam_validate_prop(known_wlan_prop_table, kwh, propname, 550*6ba597c5SAnurag S. Maskey value)); 551*6ba597c5SAnurag S. Maskey } 552*6ba597c5SAnurag S. Maskey 553*6ba597c5SAnurag S. Maskey /* 554*6ba597c5SAnurag S. Maskey * Given a property, return expected property data type 555*6ba597c5SAnurag S. Maskey */ 556*6ba597c5SAnurag S. Maskey nwam_error_t 557*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_prop_type(const char *propname, nwam_value_type_t *typep) 558*6ba597c5SAnurag S. Maskey { 559*6ba597c5SAnurag S. Maskey return (nwam_get_prop_type(known_wlan_prop_table, propname, typep)); 560*6ba597c5SAnurag S. Maskey } 561*6ba597c5SAnurag S. Maskey 562*6ba597c5SAnurag S. Maskey nwam_error_t 563*6ba597c5SAnurag S. Maskey nwam_known_wlan_prop_multivalued(const char *propname, boolean_t *multip) 564*6ba597c5SAnurag S. Maskey { 565*6ba597c5SAnurag S. Maskey return (nwam_prop_multivalued(known_wlan_prop_table, propname, multip)); 566*6ba597c5SAnurag S. Maskey } 567*6ba597c5SAnurag S. Maskey 568*6ba597c5SAnurag S. Maskey nwam_error_t 569*6ba597c5SAnurag S. Maskey nwam_known_wlan_get_default_proplist(const char ***prop_list, 570*6ba597c5SAnurag S. Maskey uint_t *numvaluesp) 571*6ba597c5SAnurag S. Maskey { 572*6ba597c5SAnurag S. Maskey return (nwam_get_default_proplist(known_wlan_prop_table, 573*6ba597c5SAnurag S. Maskey NWAM_TYPE_ANY, NWAM_CLASS_ANY, prop_list, numvaluesp)); 574*6ba597c5SAnurag S. Maskey } 575*6ba597c5SAnurag S. Maskey 576*6ba597c5SAnurag S. Maskey /* 577*6ba597c5SAnurag S. Maskey * Add the given ESSID, BSSID, secmode, keyslot and key name to known WLANs. 578*6ba597c5SAnurag S. Maskey * BSSID and keyname can be NULL. 579*6ba597c5SAnurag S. Maskey */ 580*6ba597c5SAnurag S. Maskey nwam_error_t 581*6ba597c5SAnurag S. Maskey nwam_known_wlan_add_to_known_wlans(const char *essid, const char *bssid, 582*6ba597c5SAnurag S. Maskey uint32_t secmode, uint_t keyslot, const char *keyname) 583*6ba597c5SAnurag S. Maskey { 584*6ba597c5SAnurag S. Maskey nwam_known_wlan_handle_t kwh; 585*6ba597c5SAnurag S. Maskey nwam_value_t keynameval = NULL, keyslotval = NULL, bssidsval = NULL; 586*6ba597c5SAnurag S. Maskey nwam_value_t secmodeval = NULL, priorityval = NULL; 587*6ba597c5SAnurag S. Maskey char **old_bssids = NULL, **new_bssids; 588*6ba597c5SAnurag S. Maskey uint_t nelem = 0; 589*6ba597c5SAnurag S. Maskey nwam_error_t err; 590*6ba597c5SAnurag S. Maskey int i, j; 591*6ba597c5SAnurag S. Maskey 592*6ba597c5SAnurag S. Maskey /* 593*6ba597c5SAnurag S. Maskey * Check if the given ESSID already exists as known WLAN. If so, 594*6ba597c5SAnurag S. Maskey * add the BSSID to the bssids property. If not, create one with 595*6ba597c5SAnurag S. Maskey * the given ESSID and add BSSID if given. 596*6ba597c5SAnurag S. Maskey */ 597*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_read(essid, 0, &kwh); 598*6ba597c5SAnurag S. Maskey 599*6ba597c5SAnurag S. Maskey switch (err) { 600*6ba597c5SAnurag S. Maskey case NWAM_ENTITY_NOT_FOUND: 601*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_create(essid, &kwh)) != NWAM_SUCCESS) 602*6ba597c5SAnurag S. Maskey return (err); 603*6ba597c5SAnurag S. Maskey /* New known WLAN - set priority to 0 */ 604*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64(0, &priorityval)) 605*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 606*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 607*6ba597c5SAnurag S. Maskey return (err); 608*6ba597c5SAnurag S. Maskey } 609*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 610*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_PRIORITY, priorityval); 611*6ba597c5SAnurag S. Maskey nwam_value_free(priorityval); 612*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 613*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 614*6ba597c5SAnurag S. Maskey return (err); 615*6ba597c5SAnurag S. Maskey } 616*6ba597c5SAnurag S. Maskey /* If BSSID is NULL, nothing more to do here. */ 617*6ba597c5SAnurag S. Maskey if (bssid == NULL) 618*6ba597c5SAnurag S. Maskey break; 619*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string((char *)bssid, &bssidsval)) 620*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 621*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 622*6ba597c5SAnurag S. Maskey return (err); 623*6ba597c5SAnurag S. Maskey } 624*6ba597c5SAnurag S. Maskey /* Set the bssids property */ 625*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 626*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS, bssidsval); 627*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 628*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 629*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 630*6ba597c5SAnurag S. Maskey return (err); 631*6ba597c5SAnurag S. Maskey } 632*6ba597c5SAnurag S. Maskey break; 633*6ba597c5SAnurag S. Maskey case NWAM_SUCCESS: 634*6ba597c5SAnurag S. Maskey /* If no bssid is specified, nothing to do */ 635*6ba597c5SAnurag S. Maskey if (bssid == NULL) 636*6ba597c5SAnurag S. Maskey break; 637*6ba597c5SAnurag S. Maskey 638*6ba597c5SAnurag S. Maskey /* known WLAN exists, retrieve the existing bssids property */ 639*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_get_prop_value(kwh, 640*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval); 641*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS && err != NWAM_ENTITY_NOT_FOUND) { 642*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 643*6ba597c5SAnurag S. Maskey return (err); 644*6ba597c5SAnurag S. Maskey } 645*6ba597c5SAnurag S. Maskey if (err == NWAM_SUCCESS) { 646*6ba597c5SAnurag S. Maskey if ((err = nwam_value_get_string_array(bssidsval, 647*6ba597c5SAnurag S. Maskey &old_bssids, &nelem)) != NWAM_SUCCESS) { 648*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 649*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 650*6ba597c5SAnurag S. Maskey return (err); 651*6ba597c5SAnurag S. Maskey } 652*6ba597c5SAnurag S. Maskey } 653*6ba597c5SAnurag S. Maskey /* Create a new array to append given BSSID */ 654*6ba597c5SAnurag S. Maskey new_bssids = calloc(nelem + 1, sizeof (char *)); 655*6ba597c5SAnurag S. Maskey if (new_bssids == NULL) { 656*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 657*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 658*6ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY); 659*6ba597c5SAnurag S. Maskey } 660*6ba597c5SAnurag S. Maskey 661*6ba597c5SAnurag S. Maskey /* 662*6ba597c5SAnurag S. Maskey * Copy over existing BSSIDs to the new array. Also, check 663*6ba597c5SAnurag S. Maskey * to make sure that the given BSSID doesn't already exist 664*6ba597c5SAnurag S. Maskey * in the known WLAN. If so, do abort copying and return 665*6ba597c5SAnurag S. Maskey * NWAM_SUCCESS. 666*6ba597c5SAnurag S. Maskey */ 667*6ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++) { 668*6ba597c5SAnurag S. Maskey if (strcmp(old_bssids[i], bssid) == 0) { 669*6ba597c5SAnurag S. Maskey /* nothing to do, so free up everything */ 670*6ba597c5SAnurag S. Maskey for (j = 0; j < i; j++) 671*6ba597c5SAnurag S. Maskey free(new_bssids[j]); 672*6ba597c5SAnurag S. Maskey free(new_bssids); 673*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 674*6ba597c5SAnurag S. Maskey goto set_key_info; 675*6ba597c5SAnurag S. Maskey } 676*6ba597c5SAnurag S. Maskey new_bssids[i] = strdup(old_bssids[i]); 677*6ba597c5SAnurag S. Maskey } 678*6ba597c5SAnurag S. Maskey new_bssids[nelem] = strdup(bssid); 679*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 680*6ba597c5SAnurag S. Maskey 681*6ba597c5SAnurag S. Maskey err = nwam_value_create_string_array(new_bssids, nelem + 1, 682*6ba597c5SAnurag S. Maskey &bssidsval); 683*6ba597c5SAnurag S. Maskey for (i = 0; i < nelem + 1; i++) 684*6ba597c5SAnurag S. Maskey free(new_bssids[i]); 685*6ba597c5SAnurag S. Maskey free(new_bssids); 686*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 687*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 688*6ba597c5SAnurag S. Maskey return (err); 689*6ba597c5SAnurag S. Maskey } 690*6ba597c5SAnurag S. Maskey /* Set the bssids property */ 691*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 692*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS, bssidsval); 693*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 694*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 695*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 696*6ba597c5SAnurag S. Maskey return (err); 697*6ba597c5SAnurag S. Maskey } 698*6ba597c5SAnurag S. Maskey break; 699*6ba597c5SAnurag S. Maskey default: 700*6ba597c5SAnurag S. Maskey return (err); 701*6ba597c5SAnurag S. Maskey } 702*6ba597c5SAnurag S. Maskey 703*6ba597c5SAnurag S. Maskey set_key_info: 704*6ba597c5SAnurag S. Maskey /* Set the security mode property */ 705*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64(secmode, &secmodeval)) 706*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 707*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 708*6ba597c5SAnurag S. Maskey return (err); 709*6ba597c5SAnurag S. Maskey } 710*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 711*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_SECURITY_MODE, secmodeval); 712*6ba597c5SAnurag S. Maskey nwam_value_free(secmodeval); 713*6ba597c5SAnurag S. Maskey 714*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 715*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 716*6ba597c5SAnurag S. Maskey return (err); 717*6ba597c5SAnurag S. Maskey } 718*6ba597c5SAnurag S. Maskey 719*6ba597c5SAnurag S. Maskey if (keyname != NULL) { 720*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_string((char *)keyname, 721*6ba597c5SAnurag S. Maskey &keynameval)) != NWAM_SUCCESS) { 722*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 723*6ba597c5SAnurag S. Maskey return (err); 724*6ba597c5SAnurag S. Maskey } 725*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 726*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_KEYNAME, keynameval); 727*6ba597c5SAnurag S. Maskey nwam_value_free(keynameval); 728*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 729*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 730*6ba597c5SAnurag S. Maskey return (err); 731*6ba597c5SAnurag S. Maskey } 732*6ba597c5SAnurag S. Maskey if ((err = nwam_value_create_uint64(keyslot, 733*6ba597c5SAnurag S. Maskey &keyslotval)) != NWAM_SUCCESS) { 734*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 735*6ba597c5SAnurag S. Maskey return (err); 736*6ba597c5SAnurag S. Maskey } 737*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, 738*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_KEYSLOT, keyslotval); 739*6ba597c5SAnurag S. Maskey nwam_value_free(keyslotval); 740*6ba597c5SAnurag S. Maskey } 741*6ba597c5SAnurag S. Maskey 742*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_commit(kwh, 0); 743*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 744*6ba597c5SAnurag S. Maskey 745*6ba597c5SAnurag S. Maskey return (err); 746*6ba597c5SAnurag S. Maskey } 747*6ba597c5SAnurag S. Maskey 748*6ba597c5SAnurag S. Maskey /* 749*6ba597c5SAnurag S. Maskey * Remove the given BSSID/keyname from the bssids/keyname property for the 750*6ba597c5SAnurag S. Maskey * given ESSID. 751*6ba597c5SAnurag S. Maskey */ 752*6ba597c5SAnurag S. Maskey nwam_error_t 753*6ba597c5SAnurag S. Maskey nwam_known_wlan_remove_from_known_wlans(const char *essid, const char *bssid, 754*6ba597c5SAnurag S. Maskey const char *keyname) 755*6ba597c5SAnurag S. Maskey { 756*6ba597c5SAnurag S. Maskey nwam_known_wlan_handle_t kwh; 757*6ba597c5SAnurag S. Maskey nwam_value_t bssidsval; 758*6ba597c5SAnurag S. Maskey char **old_bssids, **new_bssids; 759*6ba597c5SAnurag S. Maskey uint_t nelem; 760*6ba597c5SAnurag S. Maskey nwam_error_t err; 761*6ba597c5SAnurag S. Maskey int i, found = -1; 762*6ba597c5SAnurag S. Maskey 763*6ba597c5SAnurag S. Maskey /* Retrieve the existing bssids */ 764*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_read(essid, 0, &kwh)) != NWAM_SUCCESS) 765*6ba597c5SAnurag S. Maskey return (err); 766*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_get_prop_value(kwh, 767*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval)) != NWAM_SUCCESS) { 768*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 769*6ba597c5SAnurag S. Maskey return (err); 770*6ba597c5SAnurag S. Maskey } 771*6ba597c5SAnurag S. Maskey if ((err = nwam_value_get_string_array(bssidsval, &old_bssids, &nelem)) 772*6ba597c5SAnurag S. Maskey != NWAM_SUCCESS) { 773*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 774*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 775*6ba597c5SAnurag S. Maskey return (err); 776*6ba597c5SAnurag S. Maskey } 777*6ba597c5SAnurag S. Maskey 778*6ba597c5SAnurag S. Maskey /* Cycle through the BSSIDs array to find the BSSID to remove */ 779*6ba597c5SAnurag S. Maskey for (i = 0; i < nelem; i++) { 780*6ba597c5SAnurag S. Maskey if (strcmp(old_bssids[i], bssid) == 0) { 781*6ba597c5SAnurag S. Maskey found = i; 782*6ba597c5SAnurag S. Maskey break; 783*6ba597c5SAnurag S. Maskey } 784*6ba597c5SAnurag S. Maskey } 785*6ba597c5SAnurag S. Maskey 786*6ba597c5SAnurag S. Maskey /* Given BSSID was not found in the array */ 787*6ba597c5SAnurag S. Maskey if (found == -1) { 788*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 789*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 790*6ba597c5SAnurag S. Maskey return (NWAM_INVALID_ARG); 791*6ba597c5SAnurag S. Maskey } 792*6ba597c5SAnurag S. Maskey 793*6ba597c5SAnurag S. Maskey /* If removing the only BSSID entry, remove the bssids property */ 794*6ba597c5SAnurag S. Maskey if (nelem == 1) { 795*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 796*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_delete_prop(kwh, 797*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_BSSIDS)) != NWAM_SUCCESS) { 798*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 799*6ba597c5SAnurag S. Maskey return (err); 800*6ba597c5SAnurag S. Maskey } 801*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_commit(kwh, 0); 802*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 803*6ba597c5SAnurag S. Maskey return (err); 804*6ba597c5SAnurag S. Maskey } 805*6ba597c5SAnurag S. Maskey 806*6ba597c5SAnurag S. Maskey new_bssids = calloc(nelem - 1, sizeof (char *)); 807*6ba597c5SAnurag S. Maskey if (new_bssids == NULL) { 808*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 809*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 810*6ba597c5SAnurag S. Maskey return (NWAM_NO_MEMORY); 811*6ba597c5SAnurag S. Maskey } 812*6ba597c5SAnurag S. Maskey 813*6ba597c5SAnurag S. Maskey /* Copy over other BSSIDs */ 814*6ba597c5SAnurag S. Maskey for (i = 0; i < found; i++) 815*6ba597c5SAnurag S. Maskey new_bssids[i] = strdup(old_bssids[i]); 816*6ba597c5SAnurag S. Maskey for (i = found + 1; i < nelem; i++) 817*6ba597c5SAnurag S. Maskey new_bssids[i-1] = strdup(old_bssids[i]); 818*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 819*6ba597c5SAnurag S. Maskey 820*6ba597c5SAnurag S. Maskey err = nwam_value_create_string_array(new_bssids, nelem - 1, &bssidsval); 821*6ba597c5SAnurag S. Maskey for (i = 0; i < nelem - 1; i++) 822*6ba597c5SAnurag S. Maskey free(new_bssids[i]); 823*6ba597c5SAnurag S. Maskey free(new_bssids); 824*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 825*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 826*6ba597c5SAnurag S. Maskey return (err); 827*6ba597c5SAnurag S. Maskey } 828*6ba597c5SAnurag S. Maskey 829*6ba597c5SAnurag S. Maskey /* Set the bssids property */ 830*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_set_prop_value(kwh, NWAM_KNOWN_WLAN_PROP_BSSIDS, 831*6ba597c5SAnurag S. Maskey bssidsval); 832*6ba597c5SAnurag S. Maskey nwam_value_free(bssidsval); 833*6ba597c5SAnurag S. Maskey if (err != NWAM_SUCCESS) { 834*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 835*6ba597c5SAnurag S. Maskey return (err); 836*6ba597c5SAnurag S. Maskey } 837*6ba597c5SAnurag S. Maskey 838*6ba597c5SAnurag S. Maskey if (keyname != NULL) { 839*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_delete_prop(kwh, 840*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_KEYNAME)) != NWAM_SUCCESS) { 841*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 842*6ba597c5SAnurag S. Maskey return (err); 843*6ba597c5SAnurag S. Maskey } 844*6ba597c5SAnurag S. Maskey if ((err = nwam_known_wlan_delete_prop(kwh, 845*6ba597c5SAnurag S. Maskey NWAM_KNOWN_WLAN_PROP_KEYSLOT)) != NWAM_SUCCESS) { 846*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 847*6ba597c5SAnurag S. Maskey return (err); 848*6ba597c5SAnurag S. Maskey } 849*6ba597c5SAnurag S. Maskey } 850*6ba597c5SAnurag S. Maskey 851*6ba597c5SAnurag S. Maskey err = nwam_known_wlan_commit(kwh, 0); 852*6ba597c5SAnurag S. Maskey nwam_known_wlan_free(kwh); 853*6ba597c5SAnurag S. Maskey 854*6ba597c5SAnurag S. Maskey return (err); 855*6ba597c5SAnurag S. Maskey } 856