Author: monthadar
Date: Tue May  1 15:42:41 2012
New Revision: 234876
URL: http://svn.freebsd.org/changeset/base/234876

Log:
  Fixed some MPM reason codes and max number of neighbors check
  
   * Added IEEE80211_MESH_MAX_NEIGHBORS and it is set to 15, same as before;
   * Modified mesh_parse_meshpeering_action to verify MPM frame and send
   correct reason code for when a frame is rejected according to standard spec;
   * Modified mesh_recv_action_meshpeering_* according to the standard spec;
   * Modified mesh_peer_timeout_cb to always send CLOSE frame when in CONFIRMRCV
   state according to the standard spec;
  
  Approved by: adrian

Modified:
  head/sys/net80211/ieee80211_mesh.c
  head/sys/net80211/ieee80211_mesh.h

Modified: head/sys/net80211/ieee80211_mesh.c
==============================================================================
--- head/sys/net80211/ieee80211_mesh.c  Tue May  1 15:39:16 2012        
(r234875)
+++ head/sys/net80211/ieee80211_mesh.c  Tue May  1 15:42:41 2012        
(r234876)
@@ -1573,7 +1573,7 @@ mesh_recv_ctl(struct ieee80211_node *ni,
 }
 
 /*
- * Parse meshpeering action ie's for open+confirm frames
+ * Parse meshpeering action ie's for MPM frames
  */
 static const struct ieee80211_meshpeer_ie *
 mesh_parse_meshpeering_action(struct ieee80211_node *ni,
@@ -1583,7 +1583,9 @@ mesh_parse_meshpeering_action(struct iee
 {
        struct ieee80211vap *vap = ni->ni_vap;
        const struct ieee80211_meshpeer_ie *mpie;
+       uint16_t args[3];
        const uint8_t *meshid, *meshconf, *meshpeer;
+       uint8_t sendclose = 0; /* 1 = MPM frame rejected, close will be sent */
 
        meshid = meshconf = meshpeer = NULL;
        while (efrm - frm > 1) {
@@ -1599,6 +1601,7 @@ mesh_parse_meshpeering_action(struct iee
                        meshpeer = frm;
                        mpie = (const struct ieee80211_meshpeer_ie *) frm;
                        memset(mp, 0, sizeof(*mp));
+                       mp->peer_len = mpie->peer_len;
                        mp->peer_proto = LE_READ_2(&mpie->peer_proto);
                        mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
                        switch (subtype) {
@@ -1627,22 +1630,46 @@ mesh_parse_meshpeering_action(struct iee
        }
 
        /*
-        * Verify the contents of the frame. Action frames with
-        * close subtype don't have a Mesh Configuration IE.
-        * If if fails validation, close the peer link.
+        * Verify the contents of the frame.
+        * If it fails validation, close the peer link.
         */
-       KASSERT(meshpeer != NULL &&
-           subtype != IEEE80211_ACTION_MESHPEERING_CLOSE,
-           ("parsing close action"));
-
-       if (mesh_verify_meshid(vap, meshid) ||
-           mesh_verify_meshpeer(vap, subtype, meshpeer) ||
-           mesh_verify_meshconf(vap, meshconf)) {
-               uint16_t args[3];
+       if (mesh_verify_meshpeer(vap, subtype, (const uint8_t *)mp)) {
+               sendclose = 1;
+               IEEE80211_DISCARD(vap,
+                   IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+                   wh, NULL, "%s", "MPM validation failed");
+       }
 
+       /* If meshid is not the same reject any frames type. */
+       if (sendclose == 0 && mesh_verify_meshid(vap, meshid)) {
+               sendclose = 1;
                IEEE80211_DISCARD(vap,
                    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
                    wh, NULL, "%s", "not for our mesh");
+               if (subtype == IEEE80211_ACTION_MESHPEERING_CLOSE) {
+                       /*
+                        * Standard not clear about this, if we dont ignore
+                        * there will be an endless loop between nodes sending
+                        * CLOSE frames between each other with wrong meshid.
+                        * Discard and timers will bring FSM to IDLE state.
+                        */
+                       return NULL;
+               }
+       }
+       
+       /*
+        * Close frames are accepted if meshid is the same.
+        * Verify the other two types.
+        */
+       if (sendclose == 0 && subtype != IEEE80211_ACTION_MESHPEERING_CLOSE &&
+           mesh_verify_meshconf(vap, meshconf)) {
+               sendclose = 1;
+               IEEE80211_DISCARD(vap,
+                   IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+                   wh, NULL, "%s", "configuration missmatch");
+       }
+
+       if (sendclose) {
                vap->iv_stats.is_rx_mgtdiscard++;
                switch (ni->ni_mlstate) {
                case IEEE80211_NODE_MESH_IDLE:
@@ -1655,7 +1682,15 @@ mesh_parse_meshpeering_action(struct iee
                case IEEE80211_NODE_MESH_CONFIRMRCV:
                        args[0] = ni->ni_mlpid;
                        args[1] = ni->ni_mllid;
-                       args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
+                       /* Reason codes for rejection */
+                       switch (subtype) {
+                       case IEEE80211_ACTION_MESHPEERING_OPEN:
+                               args[2] = IEEE80211_REASON_MESH_CPVIOLATION;
+                               break;
+                       case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+                               args[2] = IEEE80211_REASON_MESH_INCONS_PARAMS;
+                               break;
+                       }
                        ieee80211_send_action(ni,
                            IEEE80211_ACTION_CAT_SELF_PROT,
                            IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -1666,6 +1701,7 @@ mesh_parse_meshpeering_action(struct iee
                }
                return NULL;
        }
+       
        return (const struct ieee80211_meshpeer_ie *) mp;
 }
 
@@ -1675,6 +1711,7 @@ mesh_recv_action_meshpeering_open(struct
        const uint8_t *frm, const uint8_t *efrm)
 {
        struct ieee80211vap *vap = ni->ni_vap;
+       struct ieee80211_mesh_state *ms = vap->iv_mesh;
        struct ieee80211_meshpeer_ie ie;
        const struct ieee80211_meshpeer_ie *meshpeer;
        uint16_t args[3];
@@ -1692,6 +1729,19 @@ mesh_recv_action_meshpeering_open(struct
 
        switch (ni->ni_mlstate) {
        case IEEE80211_NODE_MESH_IDLE:
+               /* Reject open request if reached our maximum neighbor count */
+               if (ms->ms_neighbors >= IEEE80211_MESH_MAX_NEIGHBORS) {
+                       args[0] = meshpeer->peer_llinkid;
+                       args[1] = 0;
+                       args[2] = IEEE80211_REASON_MESH_MAX_PEERS;
+                       ieee80211_send_action(ni,
+                           IEEE80211_ACTION_CAT_SELF_PROT,
+                           IEEE80211_ACTION_MESHPEERING_CLOSE,
+                           args);
+                       /* stay in IDLE state */
+                       return (0);
+               }
+               /* Open frame accepted */
                mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENRCV);
                ni->ni_mllid = meshpeer->peer_llinkid;
                ni->ni_mlpid = mesh_generateid(vap);
@@ -1792,7 +1842,8 @@ mesh_recv_action_meshpeering_open(struct
        case IEEE80211_NODE_MESH_HOLDING:
                args[0] = ni->ni_mlpid;
                args[1] = meshpeer->peer_llinkid;
-               args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+               /* Standard not clear about what the reaason code should be */
+               args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
                ieee80211_send_action(ni,
                    IEEE80211_ACTION_CAT_SELF_PROT,
                    IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -1830,11 +1881,13 @@ mesh_recv_action_meshpeering_confirm(str
                break;
        case IEEE80211_NODE_MESH_OPENSNT:
                mesh_linkchange(ni, IEEE80211_NODE_MESH_CONFIRMRCV);
+               mesh_peer_timeout_setup(ni);
                break;
        case IEEE80211_NODE_MESH_HOLDING:
                args[0] = ni->ni_mlpid;
                args[1] = meshpeer->peer_llinkid;
-               args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+               /* Standard not clear about what the reaason code should be */
+               args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
                ieee80211_send_action(ni,
                    IEEE80211_ACTION_CAT_SELF_PROT,
                    IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -1869,8 +1922,23 @@ mesh_recv_action_meshpeering_close(struc
        const struct ieee80211_frame *wh,
        const uint8_t *frm, const uint8_t *efrm)
 {
+       struct ieee80211_meshpeer_ie ie;
+       const struct ieee80211_meshpeer_ie *meshpeer;
        uint16_t args[3];
 
+       /* +2 for action + code */
+       meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2, efrm, &ie,
+           IEEE80211_ACTION_MESHPEERING_CLOSE);
+       if (meshpeer == NULL) {
+               return 0;
+       }
+
+       /*
+        * XXX: check reason code, for example we could receive
+        * IEEE80211_REASON_MESH_MAX_PEERS then we should not attempt
+        * to peer again.
+        */
+
        IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
            ni, "%s", "recv PEER CLOSE");
 
@@ -1894,7 +1962,7 @@ mesh_recv_action_meshpeering_close(struc
                break;
        case IEEE80211_NODE_MESH_HOLDING:
                mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
-               mesh_peer_timeout_setup(ni);
+               mesh_peer_timeout_stop(ni);
                break;
        }
        return 0;
@@ -2112,13 +2180,11 @@ mesh_send_action_meshpeering_close(struc
                 * mesh peer close action frame format:
                 *   [1] category
                 *   [1] action
-                *   [2] reason code
                 *   [tlv] mesh id
                 *   [tlv] mesh peer link mgmt
                 */
                *frm++ = category;
                *frm++ = action;
-               ADDSHORT(frm, args[2]);         /* reason code */
                frm = ieee80211_add_meshid(frm, vap);
                frm = ieee80211_add_meshpeer(frm,
                    IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -2260,19 +2326,13 @@ mesh_peer_timeout_cb(void *arg)
                }
                break;
        case IEEE80211_NODE_MESH_CONFIRMRCV:
-               if (ni->ni_mlrcnt == ieee80211_mesh_maxretries) {
-                       args[0] = ni->ni_mlpid;
-                       args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
-                       ieee80211_send_action(ni,
-                           IEEE80211_ACTION_CAT_SELF_PROT,
-                           IEEE80211_ACTION_MESHPEERING_CLOSE, args);
-                       ni->ni_mlrcnt = 0;
-                       mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
-                       mesh_peer_timeout_setup(ni);
-               } else {
-                       ni->ni_mlrcnt++;
-                       mesh_peer_timeout_setup(ni);
-               }
+               args[0] = ni->ni_mlpid;
+               args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
+               ieee80211_send_action(ni,
+                   IEEE80211_ACTION_CAT_SELF_PROT,
+                   IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+               mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
+               mesh_peer_timeout_setup(ni);
                break;
        case IEEE80211_NODE_MESH_HOLDING:
                mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
@@ -2418,7 +2478,8 @@ ieee80211_add_meshconf(uint8_t *frm, str
        *frm++ = IEEE80211_MESHCONF_SYNC_NEIGHOFF;
        *frm++ = IEEE80211_MESHCONF_AUTH_DISABLED;
        /* NB: set the number of neighbors before the rest */
-       *frm = (ms->ms_neighbors > 15 ? 15 : ms->ms_neighbors) << 1;
+       *frm = (ms->ms_neighbors > IEEE80211_MESH_MAX_NEIGHBORS ?
+           IEEE80211_MESH_MAX_NEIGHBORS : ms->ms_neighbors) << 1;
        if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
                *frm |= IEEE80211_MESHCONF_FORM_MP;
        frm += 1;

Modified: head/sys/net80211/ieee80211_mesh.h
==============================================================================
--- head/sys/net80211/ieee80211_mesh.h  Tue May  1 15:39:16 2012        
(r234875)
+++ head/sys/net80211/ieee80211_mesh.h  Tue May  1 15:42:41 2012        
(r234876)
@@ -32,6 +32,7 @@
 #define _NET80211_IEEE80211_MESH_H_
 
 #define        IEEE80211_MESH_DEFAULT_TTL      31
+#define        IEEE80211_MESH_MAX_NEIGHBORS    15
 
 /*
  * NB: all structures are __packed  so sizeof works on arm, et. al.
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to