802.11 network location API


Functions

int net80211_prepare_probe (struct net80211_device *dev, int band, int active)
 Prepare 802.11 device channel and rate set for scanning.
struct net80211_probe_ctxnet80211_probe_start (struct net80211_device *dev, const char *essid, int active)
 Begin probe of 802.11 networks.
int net80211_probe_step (struct net80211_probe_ctx *ctx)
 Continue probe of 802.11 networks.
struct net80211_wlannet80211_probe_finish_best (struct net80211_probe_ctx *ctx)
 Finish probe of 802.11 networks, returning best-signal network found.
struct list_headnet80211_probe_finish_all (struct net80211_probe_ctx *ctx)
 Finish probe of 802.11 networks, returning all networks found.
void net80211_free_wlan (struct net80211_wlan *wlan)
 Free WLAN structure.
void net80211_free_wlanlist (struct list_head *list)
 Free list of WLAN structures.

Function Documentation

int net80211_prepare_probe ( struct net80211_device dev,
int  band,
int  active 
)

Prepare 802.11 device channel and rate set for scanning.

Parameters:
dev 802.11 device
band RF band(s) on which to prepare for scanning
active Whether the scanning will be active
Return values:
rc Return status code

Definition at line 2064 of file net80211.c.

References assert, net80211_channel::band, net80211_device::channel, net80211_device::channels, net80211_device_operations::config, DBGC, EINVAL_ACTIVE_SCAN, net80211_device::hw, net80211_add_channels(), NET80211_BAND_BIT_2GHZ, NET80211_BAND_BIT_5GHZ, NET80211_CFG_CHANNEL, NET80211_CFG_RATE, net80211_filter_hw_channels(), NET80211_REG_TXPOWER, net80211_device::netdev, netdev_is_open(), net80211_device::nr_channels, net80211_device::nr_rates, net80211_device::op, net80211_device::rate, net80211_hw_info::rates, and net80211_device::rates.

Referenced by iwlist(), and net80211_step_associate().

02066 {
02067         assert ( netdev_is_open ( dev->netdev ) );
02068 
02069         if ( active && ( band & NET80211_BAND_BIT_5GHZ ) ) {
02070                 DBGC ( dev, "802.11 %p cannot perform active scanning on "
02071                        "5GHz band\n", dev );
02072                 return -EINVAL_ACTIVE_SCAN;
02073         }
02074 
02075         if ( band == 0 ) {
02076                 /* This can happen for a 5GHz-only card with 5GHz
02077                    scanning masked out by an active request. */
02078                 DBGC ( dev, "802.11 %p asked to prepare for scanning nothing\n",
02079                        dev );
02080                 return -EINVAL_ACTIVE_SCAN;
02081         }
02082 
02083         dev->nr_channels = 0;
02084 
02085         if ( active )
02086                 net80211_add_channels ( dev, 1, 11, NET80211_REG_TXPOWER );
02087         else {
02088                 if ( band & NET80211_BAND_BIT_2GHZ )
02089                         net80211_add_channels ( dev, 1, 14,
02090                                                 NET80211_REG_TXPOWER );
02091                 if ( band & NET80211_BAND_BIT_5GHZ )
02092                         net80211_add_channels ( dev, 36, 8,
02093                                                 NET80211_REG_TXPOWER );
02094         }
02095 
02096         net80211_filter_hw_channels ( dev );
02097 
02098         /* Use channel 1 for now */
02099         dev->channel = 0;
02100         dev->op->config ( dev, NET80211_CFG_CHANNEL );
02101 
02102         /* Always do active probes at lowest (presumably first) speed */
02103         dev->rate = 0;
02104         dev->nr_rates = 1;
02105         dev->rates[0] = dev->hw->rates[dev->channels[0].band][0];
02106         dev->op->config ( dev, NET80211_CFG_RATE );
02107 
02108         return 0;
02109 }

struct net80211_probe_ctx* net80211_probe_start ( struct net80211_device dev,
const char *  essid,
int  active 
) [read]

Begin probe of 802.11 networks.

Parameters:
dev 802.11 device
essid SSID to probe for, or "" to accept any (may not be NULL)
active Whether to use active scanning
Return values:
ctx Probe context
Active scanning may only be used on channels 1-11 in the 2.4GHz band, due to gPXE's lack of a complete regulatory database. If active scanning is used, probe packets will be sent on each channel; this can allow association with hidden-SSID networks if the SSID is properly specified.

A NULL return indicates an out-of-memory condition.

The returned context must be periodically passed to net80211_probe_step() until that function returns zero.

Definition at line 1298 of file net80211.c.

References alloc_iob(), assert, net80211_probe_ctx::beacons, net80211_device::channel, net80211_device_operations::config, currticks(), io_buffer::data, net80211_probe_ctx::dev, net80211_device::essid, net80211_probe_ctx::essid, net80211_probe_ctx::hop_step, net80211_probe_ctx::hop_time, IEEE80211_TYP_FRAME_HEADER_LEN, ieee80211_probe_req::info_element, INIT_LIST_HEAD, iob_put, iob_reserve, malloc(), NET80211_CFG_CHANNEL, net80211_keep_mgmt(), net80211_marshal_request_info(), net80211_device::netdev, netdev_is_open(), net80211_device::nr_channels, NULL, net80211_probe_ctx::old_keep_mgmt, net80211_device::op, net80211_probe_ctx::probe, strcpy(), net80211_probe_ctx::ticks_beacon, net80211_probe_ctx::ticks_channel, ticks_per_sec(), net80211_probe_ctx::ticks_start, and zalloc().

Referenced by iwlist(), and net80211_step_associate().

01301 {
01302         struct net80211_probe_ctx *ctx = zalloc ( sizeof ( *ctx ) );
01303 
01304         if ( ! ctx )
01305                 return NULL;
01306 
01307         assert ( netdev_is_open ( dev->netdev ) );
01308 
01309         ctx->dev = dev;
01310         ctx->old_keep_mgmt = net80211_keep_mgmt ( dev, 1 );
01311         ctx->essid = essid;
01312         if ( dev->essid != ctx->essid )
01313                 strcpy ( dev->essid, ctx->essid );
01314 
01315         if ( active ) {
01316                 struct ieee80211_probe_req *probe_req;
01317                 union ieee80211_ie *ie;
01318 
01319                 ctx->probe = alloc_iob ( 128 );
01320                 iob_reserve ( ctx->probe, IEEE80211_TYP_FRAME_HEADER_LEN );
01321                 probe_req = ctx->probe->data;
01322 
01323                 ie = net80211_marshal_request_info ( dev,
01324                                                      probe_req->info_element );
01325 
01326                 iob_put ( ctx->probe, ( void * ) ie - ctx->probe->data );
01327         }
01328 
01329         ctx->ticks_start = currticks();
01330         ctx->ticks_beacon = 0;
01331         ctx->ticks_channel = currticks();
01332         ctx->hop_time = ticks_per_sec() / ( active ? 2 : 6 );
01333 
01334         /*
01335          * Channels on 2.4GHz overlap, and the most commonly used
01336          * are 1, 6, and 11. We'll get a result faster if we check
01337          * every 5 channels, but in order to hit all of them the
01338          * number of channels must be relatively prime to 5. If it's
01339          * not, tweak the hop.
01340          */
01341         ctx->hop_step = 5;
01342         while ( dev->nr_channels % ctx->hop_step == 0 && ctx->hop_step > 1 )
01343                 ctx->hop_step--;
01344 
01345         ctx->beacons = malloc ( sizeof ( *ctx->beacons ) );
01346         INIT_LIST_HEAD ( ctx->beacons );
01347 
01348         dev->channel = 0;
01349         dev->op->config ( dev, NET80211_CFG_CHANNEL );
01350 
01351         return ctx;
01352 }

int net80211_probe_step ( struct net80211_probe_ctx ctx  ) 

Continue probe of 802.11 networks.

Parameters:
ctx Probe context returned by net80211_probe_start()
Return values:
rc Probe status
The return code will be 0 if the probe is still going on (and this function should be called again), a positive number if the probe completed successfully, or a negative error code if the probe failed for that reason.

Whether the probe succeeded or failed, you must call net80211_probe_finish_all() or net80211_probe_finish_best() (depending on whether you want information on all networks or just the best-signal one) in order to release the probe context. A failed probe may still have acquired some valid data.

Definition at line 1371 of file net80211.c.

References ieee80211_frame::addr3, alloc_iob(), net80211_wlan::beacon, net80211_probe_ctx::beacons, net80211_wlan::bssid, net80211_wlan::channel, net80211_device::channel, net80211_hw_info::channel_change_time, net80211_channel::channel_nr, net80211_device::channels, net80211_device_operations::config, net80211_wlan::crypto, currticks(), ieee80211_frame::data, io_buffer::data, DBG, DBGC, DBGC2, net80211_probe_ctx::dev, ENOTSUP, net80211_wlan::essid, net80211_probe_ctx::essid, ETH_ALEN, eth_ntoa(), ETIMEDOUT, ieee80211_frame::fc, free_iob(), net80211_wlan::handshaking, io_buffer::head, net80211_probe_ctx::hop_step, net80211_probe_ctx::hop_time, net80211_device::hw, ieee80211_ie::id, ieee80211_beacon, IEEE80211_CAPAB_PRIVACY, IEEE80211_FC_SUBTYPE, ieee80211_ie_bound(), IEEE80211_IE_SSID, IEEE80211_MAX_SSID_LEN, ieee80211_next_ie(), IEEE80211_STYPE_BEACON, IEEE80211_STYPE_PROBE_REQ, IEEE80211_STYPE_PROBE_RESP, iob_disown, iob_headroom(), iob_len(), iob_put, iob_reserve, ieee80211_ie::len, net80211_wlan::list, list_add_tail, list_empty(), list_for_each_entry, memcpy, NET80211_CFG_CHANNEL, NET80211_CRYPT_NONE, NET80211_CRYPT_UNKNOWN, net80211_ll_broadcast, net80211_mgmt_dequeue(), NET80211_PROBE_GATHER, NET80211_PROBE_GATHER_ALL, NET80211_PROBE_TIMEOUT, NET80211_SECPROT_NONE, NET80211_SECPROT_UNKNOWN, net80211_tx_mgmt(), net80211_device::nr_channels, NULL, net80211_device::op, net80211_probe_ctx::probe, sec80211_detect(), net80211_wlan::signal, ieee80211_ie::ssid, strcmp(), strcpy(), strerror(), io_buffer::tail, net80211_probe_ctx::ticks_beacon, net80211_probe_ctx::ticks_channel, ticks_per_sec(), net80211_probe_ctx::ticks_start, u16, u32, udelay(), and zalloc().

Referenced by iwlist(), and net80211_step_associate().

01372 {
01373         struct net80211_device *dev = ctx->dev;
01374         u32 start_timeout = NET80211_PROBE_TIMEOUT * ticks_per_sec();
01375         u32 gather_timeout = ticks_per_sec();
01376         u32 now = currticks();
01377         struct io_buffer *iob;
01378         int signal;
01379         int rc;
01380         char ssid[IEEE80211_MAX_SSID_LEN + 1];
01381 
01382         gather_timeout *= ( ctx->essid[0] ? NET80211_PROBE_GATHER :
01383                             NET80211_PROBE_GATHER_ALL );
01384 
01385         /* Time out if necessary */
01386         if ( now >= ctx->ticks_start + start_timeout )
01387                 return list_empty ( ctx->beacons ) ? -ETIMEDOUT : +1;
01388 
01389         if ( ctx->ticks_beacon > 0 && now >= ctx->ticks_start + gather_timeout )
01390                 return +1;
01391 
01392         /* Change channels if necessary */
01393         if ( now >= ctx->ticks_channel + ctx->hop_time ) {
01394                 dev->channel = ( dev->channel + ctx->hop_step )
01395                         % dev->nr_channels;
01396                 dev->op->config ( dev, NET80211_CFG_CHANNEL );
01397                 udelay ( dev->hw->channel_change_time );
01398 
01399                 ctx->ticks_channel = now;
01400 
01401                 if ( ctx->probe ) {
01402                         struct io_buffer *siob = ctx->probe; /* to send */
01403 
01404                         /* make a copy for future use */
01405                         iob = alloc_iob ( siob->tail - siob->head );
01406                         iob_reserve ( iob, iob_headroom ( siob ) );
01407                         memcpy ( iob_put ( iob, iob_len ( siob ) ),
01408                                  siob->data, iob_len ( siob ) );
01409 
01410                         ctx->probe = iob;
01411                         rc = net80211_tx_mgmt ( dev, IEEE80211_STYPE_PROBE_REQ,
01412                                                 net80211_ll_broadcast,
01413                                                 iob_disown ( siob ) );
01414                         if ( rc ) {
01415                                 DBGC ( dev, "802.11 %p send probe failed: "
01416                                        "%s\n", dev, strerror ( rc ) );
01417                                 return rc;
01418                         }
01419                 }
01420         }
01421 
01422         /* Check for new management packets */
01423         while ( ( iob = net80211_mgmt_dequeue ( dev, &signal ) ) != NULL ) {
01424                 struct ieee80211_frame *hdr;
01425                 struct ieee80211_beacon *beacon;
01426                 union ieee80211_ie *ie;
01427                 struct net80211_wlan *wlan;
01428                 u16 type;
01429 
01430                 hdr = iob->data;
01431                 type = hdr->fc & IEEE80211_FC_SUBTYPE;
01432                 beacon = ( struct ieee80211_beacon * ) hdr->data;
01433 
01434                 if ( type != IEEE80211_STYPE_BEACON &&
01435                      type != IEEE80211_STYPE_PROBE_RESP ) {
01436                         DBGC2 ( dev, "802.11 %p probe: non-beacon\n", dev );
01437                         goto drop;
01438                 }
01439 
01440                 if ( ( void * ) beacon->info_element >= iob->tail ) {
01441                         DBGC ( dev, "802.11 %p probe: beacon with no IEs\n",
01442                                dev );
01443                         goto drop;
01444                 }
01445 
01446                 ie = beacon->info_element;
01447 
01448                 if ( ! ieee80211_ie_bound ( ie, iob->tail ) )
01449                         ie = NULL;
01450 
01451                 while ( ie && ie->id != IEEE80211_IE_SSID )
01452                         ie = ieee80211_next_ie ( ie, iob->tail );
01453 
01454                 if ( ! ie ) {
01455                         DBGC ( dev, "802.11 %p probe: beacon with no SSID\n",
01456                                dev );
01457                         goto drop;
01458                 }
01459 
01460                 memcpy ( ssid, ie->ssid, ie->len );
01461                 ssid[ie->len] = 0;
01462 
01463                 if ( ctx->essid[0] && strcmp ( ctx->essid, ssid ) != 0 ) {
01464                         DBGC2 ( dev, "802.11 %p probe: beacon with wrong SSID "
01465                                 "(%s)\n", dev, ssid );
01466                         goto drop;
01467                 }
01468 
01469                 /* See if we've got an entry for this network */
01470                 list_for_each_entry ( wlan, ctx->beacons, list ) {
01471                         if ( strcmp ( wlan->essid, ssid ) != 0 )
01472                                 continue;
01473 
01474                         if ( signal < wlan->signal ) {
01475                                 DBGC2 ( dev, "802.11 %p probe: beacon for %s "
01476                                         "(%s) with weaker signal %d\n", dev,
01477                                         ssid, eth_ntoa ( hdr->addr3 ), signal );
01478                                 goto drop;
01479                         }
01480 
01481                         goto fill;
01482                 }
01483 
01484                 /* No entry yet - make one */
01485                 wlan = zalloc ( sizeof ( *wlan ) );
01486                 strcpy ( wlan->essid, ssid );
01487                 list_add_tail ( &wlan->list, ctx->beacons );
01488 
01489                 /* Whether we're using an old entry or a new one, fill
01490                    it with new data. */
01491         fill:
01492                 memcpy ( wlan->bssid, hdr->addr3, ETH_ALEN );
01493                 wlan->signal = signal;
01494                 wlan->channel = dev->channels[dev->channel].channel_nr;
01495 
01496                 /* Copy this I/O buffer into a new wlan->beacon; the
01497                  * iob we've got probably came from the device driver
01498                  * and may have the full 2.4k allocation, which we
01499                  * don't want to keep around wasting memory.
01500                  */
01501                 free_iob ( wlan->beacon );
01502                 wlan->beacon = alloc_iob ( iob_len ( iob ) );
01503                 memcpy ( iob_put ( wlan->beacon, iob_len ( iob ) ),
01504                          iob->data, iob_len ( iob ) );
01505 
01506                 if ( ( rc = sec80211_detect ( wlan->beacon, &wlan->handshaking,
01507                                               &wlan->crypto ) ) == -ENOTSUP ) {
01508                         struct ieee80211_beacon *beacon =
01509                                 ( struct ieee80211_beacon * ) hdr->data;
01510 
01511                         if ( beacon->capability & IEEE80211_CAPAB_PRIVACY ) {
01512                                 DBG ( "802.11 %p probe: secured network %s but "
01513                                       "encryption support not compiled in\n",
01514                                       dev, wlan->essid );
01515                                 wlan->handshaking = NET80211_SECPROT_UNKNOWN;
01516                                 wlan->crypto = NET80211_CRYPT_UNKNOWN;
01517                         } else {
01518                                 wlan->handshaking = NET80211_SECPROT_NONE;
01519                                 wlan->crypto = NET80211_CRYPT_NONE;
01520                         }
01521                 } else if ( rc != 0 ) {
01522                         DBGC ( dev, "802.11 %p probe warning: network "
01523                                "%s with unidentifiable security "
01524                                "settings: %s\n", dev, wlan->essid,
01525                                strerror ( rc ) );
01526                 }
01527 
01528                 ctx->ticks_beacon = now;
01529 
01530                 DBGC2 ( dev, "802.11 %p probe: good beacon for %s (%s)\n",
01531                         dev, wlan->essid, eth_ntoa ( wlan->bssid ) );
01532 
01533         drop:
01534                 free_iob ( iob );
01535         }
01536 
01537         return 0;
01538 }

struct net80211_wlan* net80211_probe_finish_best ( struct net80211_probe_ctx ctx  )  [read]

Finish probe of 802.11 networks, returning best-signal network found.

Parameters:
ctx Probe context
Return values:
wlan Best-signal network found, or NULL if none were found
If net80211_probe_start() was called with a particular SSID parameter as filter, only a network with that SSID (matching case-sensitively) can be returned from this function.

Definition at line 1552 of file net80211.c.

References net80211_probe_ctx::beacons, DBGC, net80211_probe_ctx::dev, net80211_probe_ctx::essid, free(), free_iob(), net80211_wlan::list, list_del, list_for_each_entry, net80211_free_wlanlist(), net80211_keep_mgmt(), NULL, net80211_probe_ctx::old_keep_mgmt, net80211_probe_ctx::probe, and net80211_wlan::signal.

Referenced by net80211_autoassociate(), and net80211_step_associate().

01553 {
01554         struct net80211_wlan *best = NULL, *wlan;
01555 
01556         if ( ! ctx )
01557                 return NULL;
01558 
01559         list_for_each_entry ( wlan, ctx->beacons, list ) {
01560                 if ( ! best || best->signal < wlan->signal )
01561                         best = wlan;
01562         }
01563 
01564         if ( best )
01565                 list_del ( &best->list );
01566         else
01567                 DBGC ( ctx->dev, "802.11 %p probe: found nothing for '%s'\n",
01568                        ctx->dev, ctx->essid );
01569 
01570         net80211_free_wlanlist ( ctx->beacons );
01571 
01572         net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt );
01573 
01574         if ( ctx->probe )
01575                 free_iob ( ctx->probe );
01576 
01577         free ( ctx );
01578 
01579         return best;
01580 }

struct list_head* net80211_probe_finish_all ( struct net80211_probe_ctx ctx  )  [read]

Finish probe of 802.11 networks, returning all networks found.

Parameters:
ctx Probe context
Return values:
list List of net80211_wlan detailing networks found
If net80211_probe_start() was called with a particular SSID parameter as filter, this will always return either an empty or a one-element list.

Definition at line 1593 of file net80211.c.

References net80211_probe_ctx::beacons, net80211_probe_ctx::dev, free(), free_iob(), net80211_keep_mgmt(), NULL, net80211_probe_ctx::old_keep_mgmt, and net80211_probe_ctx::probe.

Referenced by iwlist().

01594 {
01595         struct list_head *beacons = ctx->beacons;
01596 
01597         if ( ! ctx )
01598                 return NULL;
01599 
01600         net80211_keep_mgmt ( ctx->dev, ctx->old_keep_mgmt );
01601 
01602         if ( ctx->probe )
01603                 free_iob ( ctx->probe );
01604 
01605         free ( ctx );
01606 
01607         return beacons;
01608 }

void net80211_free_wlan ( struct net80211_wlan wlan  ) 

Free WLAN structure.

Parameters:
wlan WLAN structure to free

Definition at line 1616 of file net80211.c.

References net80211_wlan::beacon, free(), and free_iob().

Referenced by net80211_autoassociate(), net80211_free_wlanlist(), and net80211_step_associate().

01617 {
01618         if ( wlan ) {
01619                 free_iob ( wlan->beacon );
01620                 free ( wlan );
01621         }
01622 }

void net80211_free_wlanlist ( struct list_head list  ) 

Free list of WLAN structures.

Parameters:
list List of WLAN structures to free

Definition at line 1630 of file net80211.c.

References free(), net80211_wlan::list, list_del, list_for_each_entry_safe, and net80211_free_wlan().

Referenced by iwlist(), and net80211_probe_finish_best().

01631 {
01632         struct net80211_wlan *wlan, *tmp;
01633 
01634         if ( ! list )
01635                 return;
01636 
01637         list_for_each_entry_safe ( wlan, tmp, list, list ) {
01638                 list_del ( &wlan->list );
01639                 net80211_free_wlan ( wlan );
01640         }
01641 
01642         free ( list );
01643 }


Generated on Tue Apr 6 20:01:59 2010 for gPXE by  doxygen 1.5.7.1