From owner-svn-src-all@FreeBSD.ORG Tue May 1 15:42:41 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CB1691065672; Tue, 1 May 2012 15:42:41 +0000 (UTC) (envelope-from monthadar@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B50248FC15; Tue, 1 May 2012 15:42:41 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q41FgfTS032425; Tue, 1 May 2012 15:42:41 GMT (envelope-from monthadar@svn.freebsd.org) Received: (from monthadar@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q41Fgf4P032422; Tue, 1 May 2012 15:42:41 GMT (envelope-from monthadar@svn.freebsd.org) Message-Id: <201205011542.q41Fgf4P032422@svn.freebsd.org> From: Monthadar Al Jaberi Date: Tue, 1 May 2012 15:42:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r234876 - head/sys/net80211 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 May 2012 15:42:41 -0000 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.