summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_mesh.c
diff options
context:
space:
mode:
authormonthadar <monthadar@FreeBSD.org>2012-05-01 15:42:41 +0000
committermonthadar <monthadar@FreeBSD.org>2012-05-01 15:42:41 +0000
commit6b5007d019c581519337942352d927a5c7de4f19 (patch)
treeeafe996e651e933a50a1c7df8e341922e1a66bff /sys/net80211/ieee80211_mesh.c
parent9d51d66dc0ef2e7c01208283595f080688e7a80e (diff)
downloadFreeBSD-src-6b5007d019c581519337942352d927a5c7de4f19.zip
FreeBSD-src-6b5007d019c581519337942352d927a5c7de4f19.tar.gz
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
Diffstat (limited to 'sys/net80211/ieee80211_mesh.c')
-rw-r--r--sys/net80211/ieee80211_mesh.c125
1 files changed, 93 insertions, 32 deletions
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index 13ca62a..de39607 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -1573,7 +1573,7 @@ mesh_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
}
/*
- * 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 ieee80211_node *ni,
{
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 ieee80211_node *ni,
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 ieee80211_node *ni,
}
/*
- * 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 ieee80211_node *ni,
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 ieee80211_node *ni,
}
return NULL;
}
+
return (const struct ieee80211_meshpeer_ie *) mp;
}
@@ -1675,6 +1711,7 @@ mesh_recv_action_meshpeering_open(struct ieee80211_node *ni,
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 ieee80211_node *ni,
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 ieee80211_node *ni,
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(struct ieee80211_node *ni,
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(struct ieee80211_node *ni,
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(struct ieee80211_node *ni,
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(struct ieee80211_node *ni,
* 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, struct ieee80211vap *vap)
*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;
OpenPOWER on IntegriCloud