[802.11] Modify 802.11 layer to use ieee80211_next_ie() to step through IEs
authorJoshua Oreman <oremanj@xenon.get-linux.org>
Thu, 18 Jun 2009 22:21:09 +0000 (15:21 -0700)
committerJoshua Oreman <oremanj@xenon.get-linux.org>
Thu, 18 Jun 2009 22:21:09 +0000 (15:21 -0700)
This replaces an old method of "ie_byte += ie->len + 2; ie = ie_byte;"
that was ad-hoc and bug-prone.

src/net/net80211.c

index e182101..a27dd93 100644 (file)
@@ -124,10 +124,10 @@ static void net80211_add_channels ( struct net80211_device *dev, int start,
 static int net80211_process_capab ( struct net80211_device *dev,
                                    u16 capab );
 static int net80211_process_ie ( struct net80211_device *dev,
-                                struct ieee80211_ie *ie, int len );
-static struct ieee80211_ie *
+                                union ieee80211_ie *ie, void *ie_end );
+static union ieee80211_ie *
 net80211_marshal_request_info ( struct net80211_device *dev,
-                               struct ieee80211_ie *ie );
+                               union ieee80211_ie *ie );
 static void net80211_print_status ( struct net_device *netdev );
 
 static void net80211_step_associate ( struct process *proc );
@@ -367,7 +367,7 @@ static u16 net80211_duration ( struct net80211_device *dev, int bytes )
  * @v net_proto                Network-layer protocol, in network byte order
  * @ret rc             Return status code
  *
- * This adds both the 802.11 frame header and the 802.3 LLC/SNAP
+ * This adds both the 802.11 frame header and the 802.2 LLC/SNAP
  * header used on data packets.
  *
  * We also check here for state of the link that would make it invalid
@@ -427,7 +427,7 @@ static int net80211_ll_push ( struct net_device *netdev,
  * @ret net_proto      Network-layer protocol, in network byte order
  * @ret rc             Return status code
  *
- * This expects and removes both the 802.11 frame header and the 802.3
+ * This expects and removes both the 802.11 frame header and the 802.2
  * LLC/SNAP header that are used on data packets.
  */
 static int net80211_ll_pull ( struct net_device *netdev __unused,
@@ -857,22 +857,22 @@ static int net80211_process_capab ( struct net80211_device *dev,
  *
  * @v dev      802.11 device
  * @v ie       Pointer to first information element
- * @v len      Total length of all information elements
+ * @v ie_end   Pointer to tail of packet I/O buffer
  * @ret rc     Return status code
  */
 static int net80211_process_ie ( struct net80211_device *dev,
-                                struct ieee80211_ie *ie, int len )
+                                union ieee80211_ie *ie, void *ie_end )
 {
-       void *ie_byte = ie;
-       void *ie_byte_end = ie_byte + len;
        u16 old_rate = NET80211_RATE_VALUE ( dev->rates[dev->rate] );
        u16 old_phy = dev->phy_flags;
        int have_rates = 0, i;
        int ds_channel = 0;
        int changed = 0;
 
-       for ( ie = ie_byte; ie_byte < ie_byte_end;
-             ie_byte += ie->len + 2, ie = ie_byte ) {
+       if ( ( void * ) ie >= ie_end )
+               return 0;
+
+       for ( ; ie; ie = ieee80211_next_ie ( ie, ie_end ) ) {
                switch ( ie->id ) {
                case IEEE80211_IE_SSID:
                        if ( ie->len <= 32 ) {
@@ -917,14 +917,16 @@ static int net80211_process_ie ( struct net80211_device *dev,
                               "for %c%c\n", dev, ie->country.name[0],
                               ie->country.name[1] );
                        for ( i = 0; i < ( ie->len - 3 ) / 3; i++ ) {
-                               if ( ie->country.triplet[i].ext.reg_ext_id > 200 ) {
+                               union ieee80211_ie_country_triplet *t =
+                                       &ie->country.triplet[i];
+                               if ( t->first > 200 ) {
                                        DBGC ( dev, "802.11 %p ignoring regulatory "
                                               "extension information\n", dev );
                                } else {
                                        net80211_add_channels ( dev,
-                                         ie->country.triplet[i].band.first_channel,
-                                         ie->country.triplet[i].band.nr_channels,
-                                         ie->country.triplet[i].band.max_txpower );
+                                                       t->band.first_channel,
+                                                       t->band.nr_channels,
+                                                       t->band.max_txpower );
                                }
                        }
                        break;
@@ -998,19 +1000,17 @@ static int net80211_process_ie ( struct net80211_device *dev,
  * @v ie               Pointer to start of information element area
  * @ret next_ie                Pointer to first byte after added information elements
  */
-static struct ieee80211_ie *
+static union ieee80211_ie *
 net80211_marshal_request_info ( struct net80211_device *dev,
-                               struct ieee80211_ie *ie )
+                               union ieee80211_ie *ie )
 {
-       void *ie_byte = ie;
        int i;
 
        ie->id = IEEE80211_IE_SSID;
        ie->len = strlen ( dev->essid );
        memcpy ( ie->ssid, dev->essid, ie->len );
 
-       ie_byte += ie->len + 2;
-       ie = ie_byte;
+       ie = ieee80211_next_ie ( ie, NULL );
 
        ie->id = IEEE80211_IE_RATES;
        ie->len = dev->nr_rates;
@@ -1025,18 +1025,17 @@ net80211_marshal_request_info ( struct net80211_device *dev,
                   for the rates beyond the eighth. */
                int rates = ie->len;
 
-               memmove ( ie_byte + 2 + 8 + 2, ie_byte + 2 + 8, rates - 8 );
+               memmove ( ( void * ) ie + 2 + 8 + 2, ( void * ) ie + 2 + 8,
+                         rates - 8 );
                ie->len = 8;
 
-               ie_byte += ie->len + 2;
-               ie = ie_byte;
+               ie = ieee80211_next_ie ( ie, NULL );
 
                ie->id = IEEE80211_IE_EXT_RATES;
                ie->len = rates - 8;
        }
 
-       ie_byte += ie->len + 2;
-       ie = ie_byte;
+       ie = ieee80211_next_ie ( ie, NULL );
 
        return ie;
 }
@@ -1109,8 +1108,7 @@ struct net80211_wlan * net80211_probe ( struct net80211_device *dev,
        void *probe = NULL;
        int probe_len = 0;
        struct io_buffer *iob;
-       struct ieee80211_ie *ie;
-       void *ie_byte;
+       union ieee80211_ie *ie;
        int rc;
 
        /* Channels on 2.4GHz overlap, and the most commonly used
@@ -1146,7 +1144,7 @@ struct net80211_wlan * net80211_probe ( struct net80211_device *dev,
        while ( currticks() < start_ticks + start_timeout ) {
                struct ieee80211_frame *hdr;
                struct ieee80211_beacon *beacon; /* == iee80211_probe_resp */
-               struct ieee80211_ie *ie;
+               union ieee80211_ie *ie;
                int signal;
                u16 type;
 
@@ -1194,13 +1192,17 @@ struct net80211_wlan * net80211_probe ( struct net80211_device *dev,
                        goto drop;
                }
 
-               ie = beacon->info_element;
-               ie_byte = ie;
-               while ( ie_byte < iob->tail && ie->id != IEEE80211_IE_SSID ) {
-                       ie_byte += ie->len + 2;
-                       ie = ie_byte;
+               if ( ( void * ) beacon->info_element >= iob->tail ) {
+                       DBGC2 ( dev, "802.11 %p probe: beacon with no IEs\n",
+                               dev );
+                       goto drop;
                }
-               if ( ie_byte >= iob->tail ) {
+
+               ie = beacon->info_element;
+               while ( ie && ie->id != IEEE80211_IE_SSID )
+                       ie = ieee80211_next_ie ( ie, iob->tail );
+
+               if ( ! ie ) {
                        /* didn't find an SSID */
                        DBGC2 ( dev, "802.11 %p probe: beacon with no SSID\n",
                                dev );
@@ -1661,8 +1663,7 @@ int net80211_prepare ( struct net80211_device *dev,
                return rc;
 
        rc = net80211_process_ie ( dev, beacon->info_element,
-                                  iob_len ( wlan->beacon ) -
-                                  sizeof ( *hdr ) );
+                                  wlan->beacon->tail );
        if ( rc )
                return rc;
 
@@ -1776,8 +1777,7 @@ int net80211_send_assoc ( struct net80211_device *dev,
 {
        struct io_buffer *iob = alloc_iob ( 128 );
        struct ieee80211_assoc_req *assoc;
-       struct ieee80211_ie *ie;
-       void *ie_byte;
+       union ieee80211_ie *ie;
 
        net80211_set_state ( dev, 0, NET80211_WAITING, 0 );
 
@@ -1795,14 +1795,13 @@ int net80211_send_assoc ( struct net80211_device *dev,
        assoc->listen_interval = 1;
 
        ie = net80211_marshal_request_info ( dev, assoc->info_element );
-       ie_byte = ie;
 
        DBGP ( "802.11 %p about to send association request:\n", dev );
-       DBGP_HD ( iob->data, ie_byte - iob->data );
+       DBGP_HD ( iob->data, ( void * ) ie - iob->data );
 
        /* XXX add RSN ie for WPA support */
 
-       iob_put ( iob, ie_byte - iob->data );
+       iob_put ( iob, ( void * ) ie - iob->data );
 
        return net80211_tx_mgmt ( dev, IEEE80211_STYPE_ASSOC_REQ,
                                  wlan->bssid, iob );
@@ -1822,8 +1821,7 @@ static void net80211_handle_assoc_reply ( struct net80211_device *dev,
                ( struct ieee80211_assoc_resp * ) hdr->data;
 
        net80211_process_capab ( dev, assoc->capability );
-       net80211_process_ie ( dev, assoc->info_element,
-                             iob_len ( iob ) - sizeof ( *hdr ) );
+       net80211_process_ie ( dev, assoc->info_element, iob->tail );
 
        if ( assoc->status != IEEE80211_STATUS_SUCCESS ) {
                DBGC ( dev, "802.11 %p association failed: status %d\n",