1/* 2 * smeSelect.c 3 * 4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34/** \file smeSelect.c 35 * \brief SME select function implementation 36 * 37 * \see smeSm.h, smeSm.c, sme.c, sme.h, smePrivate.h 38 */ 39 40 41#define __FILE_ID__ FILE_ID_42 42#include "smePrivate.h" 43#include "scanResultTable.h" 44#include "rsnApi.h" 45#include "siteMgrApi.h" 46#include "EvHandler.h" 47#include "GenSM.h" 48#include "smeSm.h" 49#include "tidef.h" 50 51static TI_BOOL sme_SelectSsidMatch (TI_HANDLE hSme, TSsid *pSiteSsid, TSsid *pDesiredSsid, 52 ESsidType eDesiredSsidType); 53static TI_BOOL sme_SelectBssidMatch (TMacAddr *pSiteBssid, TMacAddr *pDesiredBssid); 54static TI_BOOL sme_SelectBssTypeMatch (ScanBssType_e eSiteBssType, ScanBssType_e eDesiredBssType); 55static TI_BOOL sme_SelectWscMatch (TI_HANDLE hSme, TSiteEntry *pCurrentSite, 56 TI_BOOL *pbWscPbAbort, TI_BOOL *pbWscPbApFound); 57static TI_BOOL sme_SelectRsnMatch (TI_HANDLE hSme, TSiteEntry *pCurrentSite); 58 59/** 60 * \fn sme_Select 61 * \brief Select a connection candidate from the scan result table 62 * 63 * Select a connection candidate from the scan result table. 64 * 65 * Connection candidate must match SSID, BSSID, BSS type, RSN and WSC settings, has the best 66 * RSSI level from all matching sites, and connection was not attempted to it in this SME cycle 67 * (since last scan was completed) 68 * 69 * \param hSme - handle to the SME object 70 * \return A pointer to the selected site, NULL if no site macthes the selection criteria 71 */ 72TSiteEntry *sme_Select (TI_HANDLE hSme) 73{ 74 TSme *pSme = (TSme*)hSme; 75 TSiteEntry *pCurrentSite, *pSelectedSite = NULL; 76 TI_INT8 iSelectedSiteRssi = -127; /* minimum RSSI */ 77 TI_BOOL bWscPbAbort, pWscPbApFound = TI_FALSE; 78 int apFoundCtr =0; 79 80 TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select called\n"); 81 82 /* on SG avalanche, select is not needed, send connect event automatically */ 83 if (TI_TRUE == pSme->bReselect) 84 { 85 paramInfo_t *pParam; 86 87 TRACE0(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: reselect flag is on, reselecting the current site\n"); 88 89 pParam = (paramInfo_t *)os_memoryAlloc(pSme->hOS, sizeof(paramInfo_t)); 90 if (!pParam) 91 return NULL; 92 93 pSme->bReselect = TI_FALSE; 94 95 /* Get Primary Site */ 96 pParam->paramType = SITE_MGR_GET_PRIMARY_SITE; 97 siteMgr_getParam(pSme->hSiteMgr, pParam); 98 pCurrentSite = pParam->content.pPrimarySite; 99 os_memoryFree(pSme->hOS, pParam, sizeof(paramInfo_t)); 100 return pCurrentSite; 101 } 102 103 /* get the first site from the scan result table */ 104 pCurrentSite = scanResultTable_GetFirst (pSme->hScanResultTable); 105 106 /* check all sites */ 107 while (NULL != pCurrentSite) 108 { 109 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: considering BSSID: %02x:%02x:%02x:%02x:%02x:%02x for selection\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 110 111 /* if this site was previously selected in the current SME connection attempt, and conn mode is auto */ 112 if (TI_TRUE == pCurrentSite->bConsideredForSelect) 113 { 114 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x was selected previously\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 115 /* get the next site and continue the loop */ 116 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 117 continue; 118 } 119 120 /* check if site matches */ 121 /* first check SSID match */ 122 if (TI_FALSE == sme_SelectSsidMatch (hSme, &(pCurrentSite->ssid), &(pSme->tSsid), pSme->eSsidType)) 123 /* site doesn't match */ 124 { 125 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x doesn't match SSID\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 126 pCurrentSite->bConsideredForSelect = TI_TRUE; /* don't try this site again */ 127 /* get the next site and continue the loop */ 128 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 129 continue; 130 } 131 132 /* Now check BSSID match */ 133 if (TI_FALSE == sme_SelectBssidMatch (&(pCurrentSite->bssid), &(pSme->tBssid))) 134 /* site doesn't match */ 135 { 136 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x doesn't match SSID\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 137 pCurrentSite->bConsideredForSelect = TI_TRUE; /* don't try this site again */ 138 /* get the next site and continue the loop */ 139 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 140 continue; 141 } 142 143 /* and BSS type match */ 144 if (TI_FALSE == sme_SelectBssTypeMatch (pCurrentSite->bssType, pSme->eBssType)) 145 /* site doesn't match */ 146 { 147 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x doesn't match BSS type\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 148 pCurrentSite->bConsideredForSelect = TI_TRUE; /* don't try this site again */ 149 /* get the next site and continue the loop */ 150 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 151 continue; 152 } 153 154 if (pCurrentSite->WSCSiteMode == TIWLN_SIMPLE_CONFIG_PBC_METHOD) 155 { 156 apFoundCtr++; 157 } 158 if (apFoundCtr > 1) 159 { 160 pWscPbApFound = TI_TRUE; 161 } 162 163 /* and simple config match */ 164 if (TI_FALSE == sme_SelectWscMatch (hSme, pCurrentSite, &bWscPbAbort, &pWscPbApFound)) 165 /* site doesn't match */ 166 { 167 /* also check if abort was indicated */ 168 if (TI_TRUE == bWscPbAbort) 169 { 170 /* send event to user mode to indicate this */ 171 EvHandlerSendEvent (pSme->hEvHandler, IPC_EVENT_WPS_SESSION_OVERLAP, NULL, 0); 172 /* select failed - will rescan in time */ 173 return NULL; 174 } 175 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x doesn't match WSC\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 176 pCurrentSite->bConsideredForSelect = TI_TRUE; /* don't try this site again */ 177 /* get the next site and continue the loop */ 178 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 179 continue; 180 } 181 182 /* and security match */ 183 if (TI_FALSE == sme_SelectRsnMatch (hSme, pCurrentSite)) 184 /* site doesn't match */ 185 { 186 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x doesn't match RSN\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 187 pCurrentSite->bConsideredForSelect = TI_TRUE; /* don't try this site again */ 188 /* get the next site and continue the loop */ 189 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 190 continue; 191 } 192 193 /* and rate match */ 194 if (TI_FALSE == siteMgr_SelectRateMatch (pSme->hSiteMgr, pCurrentSite)) 195 /* site doesn't match */ 196 { 197 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x doesn't match rates\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 198 pCurrentSite->bConsideredForSelect = TI_TRUE; /* don't try this site again */ 199 /* get the next site and continue the loop */ 200 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 201 continue; 202 } 203 204 /* if this site RSSI is higher than current maximum, select it */ 205 if (pCurrentSite->rssi > iSelectedSiteRssi) 206 { 207 TRACE6(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_Select: BSSID: %02x:%02x:%02x:%02x:%02x:%02x match and has highest RSSI so far!\n", pCurrentSite->bssid[ 0 ], pCurrentSite->bssid[ 1 ], pCurrentSite->bssid[ 2 ], pCurrentSite->bssid[ 3 ], pCurrentSite->bssid[ 4 ], pCurrentSite->bssid[ 5 ]); 208 pSelectedSite = pCurrentSite; 209 iSelectedSiteRssi = pCurrentSite->rssi; 210 } 211 212 /* and continue to the next site */ 213 pCurrentSite = scanResultTable_GetNext (pSme->hScanResultTable); 214 } 215 216 /* if a matching site was found */ 217 if (NULL != pSelectedSite) 218 { 219 /* mark that a connection to this site was (actually is) attempted */ 220 pSelectedSite->bConsideredForSelect = TI_TRUE; 221 222 /* hope this is the correct place for siteMgr_changeBandParams */ 223 siteMgr_changeBandParams (pSme->hSiteMgr, pSelectedSite->eBand); 224 225 /* 226 * Coordinate between SME module site table and Site module site Table 227 * copy candidate AP to Site module site Table. 228 */ 229 siteMgr_CopyToPrimarySite(pSme->hSiteMgr, pSelectedSite); 230 } 231 232 /* return the selected site (or NULL, if no site was selected) */ 233 return pSelectedSite; 234} 235 236/** 237 * \fn sme_SelectSsidMatch 238 * \brief Check if a site SSID matches the desired SSID for selection 239 * 240 * Check if a site SSID matches the desired SSID for selection 241 * 242 * \param hSme - handle to the SME object 243 * \param pSiteSsid - the site SSID 244 * \param pDesiredSsid - the desired SSID 245 * \param edesiredSsidType - the desired SSID type 246 * \return TI_TRUE if SSIDs match, TI_FALSE if they don't 247 * \sa sme_Select 248 */ 249TI_BOOL sme_SelectSsidMatch (TI_HANDLE hSme, TSsid *pSiteSsid, TSsid *pDesiredSsid, 250 ESsidType eDesiredSsidType) 251{ 252 TSme *pSme = (TSme*)hSme; 253 254 /* if the desired SSID type is any, return TRUE (site matches) */ 255 if (SSID_TYPE_ANY == eDesiredSsidType) 256 { 257 return TI_TRUE; 258 } 259 260 /* otherwise, check if the SSIDs match */ 261 if ((pSiteSsid->len == pDesiredSsid->len) && /* lngth match */ 262 (0 == os_memoryCompare (pSme->hOS, &(pSiteSsid->str[ 0 ]), &(pDesiredSsid->str[ 0 ]), pSiteSsid->len))) /* content match */ 263 { 264 return TI_TRUE; 265 } 266 else 267 { 268 return TI_FALSE; 269 } 270} 271 272/** 273 * \fn sme_SelectBssidMatch 274 * \brief Check if a site BSSID matches the desired BSSID for selection 275 * 276 * Check if a site BSSID matches the desired BSSID for selection 277 * 278 * \param pSiteBssid - the site BSSID 279 * \param pDesiredBssid - the desired BSSID 280 * \return TI_TRUE if BSSIDs match, TI_FALSE if they don't 281 * \sa sme_Select 282 */ 283TI_BOOL sme_SelectBssidMatch (TMacAddr *pSiteBssid, TMacAddr *pDesiredBssid) 284{ 285 /* check if the desired BSSID is broadcast (no need to match) */ 286 if (TI_TRUE == MAC_BROADCAST (*pDesiredBssid)) 287 { 288 return TI_TRUE; 289 } 290 291 /* if the desired BSSID is not any BSSID, check if the site BSSID equals the desired BSSID */ 292 if (TI_TRUE == MAC_EQUAL (*pDesiredBssid, *pSiteBssid)) 293 { 294 return TI_TRUE; 295 } 296 297 /* no match */ 298 return TI_FALSE; 299} 300 301/** 302 * \fn sme_SelectBssTypeMatch 303 * \brief Checks if the desired BSS type match the BSS type of a site 304 * 305 * Checks if the desired BSS type match the BSS type of a site 306 * 307 * \param eSiteBssType - the site BSS type 308 * \param edesiredBssType - the desired BSS type 309 * \return TI_TRUE if the BSS types matches, TI_FALSE if they don't 310 * \sa sme_Select 311 */ 312TI_BOOL sme_SelectBssTypeMatch (ScanBssType_e eSiteBssType, ScanBssType_e eDesiredBssType) 313{ 314 /* if the desired type is any, there is a match */ 315 if (BSS_ANY == eDesiredBssType) 316 { 317 return TI_TRUE; 318 } 319 320 /* if the BSS types equal, there is a match */ 321 if (eDesiredBssType == eSiteBssType) 322 { 323 return TI_TRUE; 324 } 325 326 /* no match */ 327 return TI_FALSE; 328} 329 330/** 331 * \fn sme_SelectWscMatch 332 * \brief checks if the configred WSC mode equals the WSC mode of a site 333 * 334 * checks if the configred WSC mode equals the WSC mode of a site 335 * 336 * \param hSme - handle to the SME object 337 * \param pCurrentSite - site to check 338 * \return TI_TRUE if site macthes current WSC mode, TI_FALSE if it doesn't match 339 * \sa sme_Select 340 */ 341TI_BOOL sme_SelectWscMatch (TI_HANDLE hSme, TSiteEntry *pCurrentSite, 342 TI_BOOL *pbWscPbAbort, TI_BOOL *pbWscPbApFound) 343{ 344 TSme *pSme = (TSme*)hSme; 345 TIWLN_SIMPLE_CONFIG_MODE wscMode; 346 347 siteMgr_getParamWSC(pSme->hSiteMgr, &wscMode); /* SITE_MGR_SIMPLE_CONFIG_MODE - get the WSC mode from site mgr */ 348 /* if simple config is off, site match */ 349 if (TIWLN_SIMPLE_CONFIG_OFF == wscMode) 350 { 351 return TI_TRUE; 352 } 353 354 /* if WSC is supported, and more than one AP with PB configuration is found - indicate to abort */ 355 if ((TI_TRUE == *pbWscPbApFound) && (TIWLN_SIMPLE_CONFIG_PBC_METHOD == pCurrentSite->WSCSiteMode)) 356 { 357 TRACE1(pSme->hReport, REPORT_SEVERITY_INFORMATION , "sme_SelectWscMatch: WSC mode is %d, and more than one AP with WSC PB found - aborting\n", wscMode); 358 *pbWscPbAbort = TI_TRUE; 359 return TI_FALSE; 360 } 361 else 362 { 363 /* indicate NOT to abort the select process */ 364 *pbWscPbAbort = TI_FALSE; 365 } 366 367 /* if configured simple config mode equals site simple config mode, site match */ 368 if (pCurrentSite->WSCSiteMode == wscMode) 369 { 370 return TI_TRUE; 371 } 372 373 /* site doesn't match */ 374 return TI_FALSE; 375} 376 377/** 378 * \fn sme_SelectRsnMatch 379 * \brief Checks if the configured scurity settings match those of a site 380 * 381 * Checks if the configured scurity settings match those of a site 382 * 383 * \param hSme - handle to the SME object 384 * \param pCurrentSite - the site to check 385 * \return TI_TRUE if site matches RSN settings, TI FALSE if it doesn't 386 * \sa sme_Select 387 */ 388TI_BOOL sme_SelectRsnMatch (TI_HANDLE hSme, TSiteEntry *pCurrentSite) 389{ 390 TSme *pSme = (TSme*)hSme; 391 TRsnData tRsnData; 392 dot11_RSN_t *pRsnIe; 393 TI_UINT8 uRsnIECount=0; 394 TI_UINT8 uCurRsnData[255]; 395 TI_UINT8 uLength = 0; 396 TI_UINT32 uMetric; 397 TRsnSiteParams tRsnSiteParams; 398 399 tRsnSiteParams.bssType = pCurrentSite->bssType; 400 MAC_COPY(tRsnSiteParams.bssid, pCurrentSite->bssid); 401 tRsnSiteParams.pHTCapabilities = &pCurrentSite->tHtCapabilities; 402 tRsnSiteParams.pHTInfo = &pCurrentSite->tHtInformation; 403 404 /* copy all RSN IE's */ 405 pRsnIe = pCurrentSite->pRsnIe; 406 while ((uLength < pCurrentSite->rsnIeLen) && (uRsnIECount < MAX_RSN_IE)) 407 { 408 uCurRsnData[ 0 + uLength ] = pRsnIe->hdr[ 0 ]; 409 uCurRsnData[ 1 + uLength ] = pRsnIe->hdr[ 1 ]; 410 os_memoryCopy (pSme->hOS, &uCurRsnData[ 2 + uLength ], pRsnIe->rsnIeData, pRsnIe->hdr[ 1 ]); 411 uLength += pRsnIe->hdr[ 1 ] + 2; 412 pRsnIe += 1; 413 uRsnIECount++; 414 } 415 /* sanity check - make sure RSN IE's size is not too big */ 416 if (uLength < pCurrentSite->rsnIeLen) 417 { 418 TRACE2(pSme->hReport, REPORT_SEVERITY_ERROR , "sme_SelectRsnMatch, RSN IE is too long: rsnIeLen=%d, MAX_RSN_IE=%d\n", pCurrentSite->rsnIeLen, MAX_RSN_IE); 419 } 420 421 /* call the RSN to evaluate the site */ 422 tRsnData.pIe = (pCurrentSite->rsnIeLen == 0) ? NULL : uCurRsnData; 423 tRsnData.ieLen = pCurrentSite->rsnIeLen; 424 tRsnData.privacy = pCurrentSite->privacy; 425 if (rsn_evalSite (pSme->hRsn, &tRsnData, &tRsnSiteParams , &uMetric) != TI_OK) 426 { 427 /* no match */ 428 return TI_FALSE; 429 } 430 else 431 { 432 /* match! */ 433 return TI_TRUE; 434 } 435} 436 437