• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
51 static TI_BOOL sme_SelectSsidMatch (TI_HANDLE hSme, TSsid *pSiteSsid, TSsid *pDesiredSsid,
52                                     ESsidType eDesiredSsidType);
53 static TI_BOOL sme_SelectBssidMatch (TMacAddr *pSiteBssid, TMacAddr *pDesiredBssid);
54 static TI_BOOL sme_SelectBssTypeMatch (ScanBssType_e eSiteBssType, ScanBssType_e eDesiredBssType);
55 static TI_BOOL sme_SelectWscMatch (TI_HANDLE hSme, TSiteEntry *pCurrentSite,
56                                    TI_BOOL *pbWscPbAbort, TI_BOOL *pbWscPbApFound);
57 static 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  */
sme_Select(TI_HANDLE hSme)72 TSiteEntry *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  */
sme_SelectSsidMatch(TI_HANDLE hSme,TSsid * pSiteSsid,TSsid * pDesiredSsid,ESsidType eDesiredSsidType)249 TI_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  */
sme_SelectBssidMatch(TMacAddr * pSiteBssid,TMacAddr * pDesiredBssid)283 TI_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  */
sme_SelectBssTypeMatch(ScanBssType_e eSiteBssType,ScanBssType_e eDesiredBssType)312 TI_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  */
sme_SelectWscMatch(TI_HANDLE hSme,TSiteEntry * pCurrentSite,TI_BOOL * pbWscPbAbort,TI_BOOL * pbWscPbApFound)341 TI_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  */
sme_SelectRsnMatch(TI_HANDLE hSme,TSiteEntry * pCurrentSite)388 TI_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