diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index 5ddca24e69f4..712c2a8dcb2d 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -708,7 +708,7 @@ enum { IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ /* - * 802.11s IEs based on D3.0 spec and were not assigned by + * 802.11s IEs based on D3.03 spec and were not assigned by * ANA. Beware changing them because some of them are being * kept compatible with Linux. */ @@ -726,10 +726,9 @@ enum { IEEE80211_ELEMID_MESHPREQ = 68, IEEE80211_ELEMID_MESHPREP = 69, IEEE80211_ELEMID_MESHPERR = 70, - IEEE80211_ELEMID_MESHPU = 53, - IEEE80211_ELEMID_MESHPUC = 54, + IEEE80211_ELEMID_MESHPXU = 53, + IEEE80211_ELEMID_MESHPXUC = 54, IEEE80211_ELEMID_MESHAH = 60, /* Abbreviated Handshake */ - IEEE80211_ELEMID_MESHPEERVER = 80, /* Peering Protocol Version */ }; struct ieee80211_tim_ie { @@ -925,6 +924,9 @@ enum { IEEE80211_REASON_MESH_INVALID_GTK = 8, /* 11s */ IEEE80211_REASON_MESH_INCONS_PARAMS = 9, /* 11s */ IEEE80211_REASON_MESH_INVALID_SECURITY = 10, /* 11s */ + IEEE80211_REASON_MESH_PERR_UNSPEC = 11, /* 11s */ + IEEE80211_REASON_MESH_PERR_NO_FI = 12, /* 11s */ + IEEE80211_REASON_MESH_PERR_DEST_UNREACH = 13, /* 11s */ IEEE80211_STATUS_SUCCESS = 0, IEEE80211_STATUS_UNSPECIFIED = 1, diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 040941e8425d..2468169122ab 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -188,10 +188,7 @@ SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, rannint, CTLTYPE_INT | CTLFLAG_RW, #define IEEE80211_HWMP_DEFAULT_MAXHOPS 31 -static ieee80211_recv_action_func hwmp_recv_action_meshpath_preq; -static ieee80211_recv_action_func hwmp_recv_action_meshpath_prep; -static ieee80211_recv_action_func hwmp_recv_action_meshpath_perr; -static ieee80211_recv_action_func hwmp_recv_action_meshpath_rann; +static ieee80211_recv_action_func hwmp_recv_action_meshpath; static struct ieee80211_mesh_proto_path mesh_proto_hwmp = { .mpp_descr = "HWMP", @@ -217,16 +214,10 @@ ieee80211_hwmp_init(void) ieee80211_hwmp_rannint = msecs_to_ticks(1*1000); /* - * Register action frame handlers. + * Register action frame handler. */ ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_REQ, hwmp_recv_action_meshpath_preq); - ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_REP, hwmp_recv_action_meshpath_prep); - ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_ERR, hwmp_recv_action_meshpath_perr); - ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH, - IEEE80211_ACTION_MESHPATH_RANN, hwmp_recv_action_meshpath_rann); + IEEE80211_ACTION_MESHPATH_SEL, hwmp_recv_action_meshpath); /* NB: default is 5 secs per spec */ mesh_proto_hwmp.mpp_inact = msecs_to_ticks(5*1000); @@ -285,17 +276,23 @@ hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg) } static int -hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni, +hwmp_recv_action_meshpath(struct ieee80211_node *ni, const struct ieee80211_frame *wh, const uint8_t *frm, const uint8_t *efrm) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_meshpreq_ie preq; + struct ieee80211_meshprep_ie prep; + struct ieee80211_meshperr_ie perr; + struct ieee80211_meshrann_ie rann; const uint8_t *iefrm = frm + 2; /* action + code */ + int found = 0; while (efrm - iefrm > 1) { IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHPREQ) { + switch (*iefrm) { + case IEEE80211_ELEMID_MESHPREQ: + { const struct ieee80211_meshpreq_ie *mpreq = (const struct ieee80211_meshpreq_ie *) iefrm; /* XXX > 1 target */ @@ -305,7 +302,7 @@ hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, wh, NULL, "%s", "PREQ with wrong len"); vap->iv_stats.is_rx_mgtdiscard++; - return 1; + break; } memcpy(&preq, mpreq, sizeof(preq)); preq.preq_id = LE_READ_4(&mpreq->preq_id); @@ -315,28 +312,11 @@ hwmp_recv_action_meshpath_preq(struct ieee80211_node *ni, preq.preq_targets[0].target_seq = LE_READ_4(&mpreq->preq_targets[0].target_seq); hwmp_recv_preq(vap, ni, wh, &preq); - return 0; + found++; + break; } - iefrm += iefrm[1] + 2; - } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "PREQ without IE"); - vap->iv_stats.is_rx_mgtdiscard++; - return 0; -} - -static int -hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni, - const struct ieee80211_frame *wh, - const uint8_t *frm, const uint8_t *efrm) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211_meshprep_ie prep; - const uint8_t *iefrm = frm + 2; /* action + code */ - - while (efrm - iefrm > 1) { - IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHPREP) { + case IEEE80211_ELEMID_MESHPREP: + { const struct ieee80211_meshprep_ie *mprep = (const struct ieee80211_meshprep_ie *) iefrm; if (mprep->prep_len != @@ -345,7 +325,7 @@ hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, wh, NULL, "%s", "PREP with wrong len"); vap->iv_stats.is_rx_mgtdiscard++; - return 1; + break; } memcpy(&prep, mprep, sizeof(prep)); prep.prep_targetseq = LE_READ_4(&mprep->prep_targetseq); @@ -353,28 +333,11 @@ hwmp_recv_action_meshpath_prep(struct ieee80211_node *ni, prep.prep_metric = LE_READ_4(&mprep->prep_metric); prep.prep_origseq = LE_READ_4(&mprep->prep_origseq); hwmp_recv_prep(vap, ni, wh, &prep); - return 0; + found++; + break; } - iefrm += iefrm[1] + 2; - } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "PREP without IE"); - vap->iv_stats.is_rx_mgtdiscard++; - return 0; -} - -static int -hwmp_recv_action_meshpath_perr(struct ieee80211_node *ni, - const struct ieee80211_frame *wh, - const uint8_t *frm, const uint8_t *efrm) -{ - struct ieee80211_meshperr_ie perr; - struct ieee80211vap *vap = ni->ni_vap; - const uint8_t *iefrm = frm + 2; /* action + code */ - - while (efrm - iefrm > 1) { - IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHPERR) { + case IEEE80211_ELEMID_MESHPERR: + { const struct ieee80211_meshperr_ie *mperr = (const struct ieee80211_meshperr_ie *) iefrm; /* XXX > 1 target */ @@ -384,34 +347,17 @@ hwmp_recv_action_meshpath_perr(struct ieee80211_node *ni, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, wh, NULL, "%s", "PERR with wrong len"); vap->iv_stats.is_rx_mgtdiscard++; - return 1; + break; } memcpy(&perr, mperr, sizeof(perr)); perr.perr_dests[0].dest_seq = LE_READ_4(&mperr->perr_dests[0].dest_seq); hwmp_recv_perr(vap, ni, wh, &perr); - return 0; + found++; + break; } - iefrm += iefrm[1] + 2; - } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "PERR without IE"); - vap->iv_stats.is_rx_mgtdiscard++; - return 0; -} - -static int -hwmp_recv_action_meshpath_rann(struct ieee80211_node *ni, - const struct ieee80211_frame *wh, - const uint8_t *frm, const uint8_t *efrm) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211_meshrann_ie rann; - const uint8_t *iefrm = frm + 2; /* action + code */ - - while (efrm - iefrm > 1) { - IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); - if (*iefrm == IEEE80211_ELEMID_MESHRANN) { + case IEEE80211_ELEMID_MESHRANN: + { const struct ieee80211_meshrann_ie *mrann = (const struct ieee80211_meshrann_ie *) iefrm; if (mrann->rann_len != @@ -426,13 +372,18 @@ hwmp_recv_action_meshpath_rann(struct ieee80211_node *ni, rann.rann_seq = LE_READ_4(&mrann->rann_seq); rann.rann_metric = LE_READ_4(&mrann->rann_metric); hwmp_recv_rann(vap, ni, wh, &rann); - return 0; + found++; + break; + } } iefrm += iefrm[1] + 2; } - IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, - wh, NULL, "%s", "RANN without IE"); - vap->iv_stats.is_rx_mgtdiscard++; + if (!found) { + IEEE80211_DISCARD(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, + wh, NULL, "%s", "PATH SEL action without IE"); + vap->iv_stats.is_rx_mgtdiscard++; + } return 0; } @@ -480,24 +431,21 @@ hwmp_send_action(struct ieee80211_node *ni, return ENOMEM; } *frm++ = IEEE80211_ACTION_CAT_MESHPATH; + *frm++ = IEEE80211_ACTION_MESHPATH_SEL; switch (*ie) { case IEEE80211_ELEMID_MESHPREQ: - *frm++ = IEEE80211_ACTION_MESHPATH_REQ; frm = hwmp_add_meshpreq(frm, (struct ieee80211_meshpreq_ie *)ie); break; case IEEE80211_ELEMID_MESHPREP: - *frm++ = IEEE80211_ACTION_MESHPATH_REP; frm = hwmp_add_meshprep(frm, (struct ieee80211_meshprep_ie *)ie); break; case IEEE80211_ELEMID_MESHPERR: - *frm++ = IEEE80211_ACTION_MESHPATH_ERR; frm = hwmp_add_meshperr(frm, (struct ieee80211_meshperr_ie *)ie); break; case IEEE80211_ELEMID_MESHRANN: - *frm++ = IEEE80211_ACTION_MESHPATH_RANN; frm = hwmp_add_meshrann(frm, (struct ieee80211_meshrann_ie *)ie); break; @@ -528,6 +476,11 @@ hwmp_send_action(struct ieee80211_node *ni, return ic->ic_raw_xmit(ni, m, ¶ms); } +#define ADDSHORT(frm, v) do { \ + frm[0] = (v) & 0xff; \ + frm[1] = (v) >> 8; \ + frm += 2; \ +} while (0) #define ADDWORD(frm, v) do { \ LE_WRITE_4(frm, v); \ frm += 4; \ @@ -592,12 +545,14 @@ hwmp_add_meshperr(uint8_t *frm, const struct ieee80211_meshperr_ie *perr) *frm++ = IEEE80211_ELEMID_MESHPERR; *frm++ = sizeof(struct ieee80211_meshperr_ie) - 2 + (perr->perr_ndests - 1) * sizeof(*perr->perr_dests); - *frm++ = perr->perr_mode; + *frm++ = perr->perr_ttl; *frm++ = perr->perr_ndests; for (i = 0; i < perr->perr_ndests; i++) { + *frm += perr->perr_dests[i].dest_flags; IEEE80211_ADDR_COPY(frm, perr->perr_dests[i].dest_addr); frm += 6; ADDWORD(frm, perr->perr_dests[i].dest_seq); + ADDSHORT(frm, perr->perr_dests[i].dest_rcode); } return frm; } @@ -1138,12 +1093,15 @@ hwmp_send_prep(struct ieee80211_node *ni, sizeof(struct ieee80211_meshprep_ie)); } +#define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags #define PERR_DADDR(n) perr.perr_dests[n].dest_addr #define PERR_DSEQ(n) perr.perr_dests[n].dest_seq +#define PERR_DRCODE(n) perr.perr_dests[n].dest_rcode static void hwmp_peerdown(struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_meshperr_ie perr; struct ieee80211_mesh_route *rt; struct ieee80211_hwmp_route *hr; @@ -1154,19 +1112,27 @@ hwmp_peerdown(struct ieee80211_node *ni) hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "%s", "delete route entry"); - perr.perr_mode = 0; + perr.perr_ttl = ms->ms_ttl; perr.perr_ndests = 1; + if (hr->hr_seq == 0) + PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN; + PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC; IEEE80211_ADDR_COPY(PERR_DADDR(0), rt->rt_dest); PERR_DSEQ(0) = hr->hr_seq; + PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH; /* NB: flush everything passing through peer */ ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr); hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr); } +#undef PERR_DFLAGS #undef PERR_DADDR #undef PERR_DSEQ +#undef PERR_DRCODE +#define PERR_DFLAGS(n) perr->perr_dests[n].dest_flags #define PERR_DADDR(n) perr->perr_dests[n].dest_addr #define PERR_DSEQ(n) perr->perr_dests[n].dest_seq +#define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode static void hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, const struct ieee80211_frame *wh, const struct ieee80211_meshperr_ie *perr) @@ -1192,9 +1158,9 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i)); if (rt == NULL) continue; - hr = IEEE80211_MESH_ROUTE_PRIV(rt, - struct ieee80211_hwmp_route); - if (HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) { + hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); + if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) && + HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) { ieee80211_mesh_rt_del(vap, rt->rt_dest); ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest); rt = NULL; @@ -1205,10 +1171,11 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, * Propagate the PERR if we previously found it on our routing table. * XXX handle ndest > 1 */ - if (forward) { + if (forward && perr->perr_ttl > 1) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "propagate PERR from %s", ether_sprintf(wh->i_addr2)); memcpy(&pperr, perr, sizeof(*perr)); + pperr.perr_ttl--; hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &pperr); } diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 722749576ba3..b0bfe8892d07 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -87,10 +87,10 @@ static void mesh_peer_timeout_backoff(struct ieee80211_node *); static void mesh_peer_timeout_cb(void *); static __inline void mesh_peer_timeout_stop(struct ieee80211_node *); -static int mesh_verify_meshpeerver(struct ieee80211vap *, const uint8_t *); static int mesh_verify_meshid(struct ieee80211vap *, const uint8_t *); static int mesh_verify_meshconf(struct ieee80211vap *, const uint8_t *); -static int mesh_verify_meshpeer(struct ieee80211vap *, const uint8_t *); +static int mesh_verify_meshpeer(struct ieee80211vap *, uint8_t, + const uint8_t *); uint32_t mesh_airtime_calc(struct ieee80211_node *); /* @@ -1544,19 +1544,16 @@ static const struct ieee80211_meshpeer_ie * mesh_parse_meshpeering_action(struct ieee80211_node *ni, const struct ieee80211_frame *wh, /* XXX for VERIFY_LENGTH */ const uint8_t *frm, const uint8_t *efrm, - struct ieee80211_meshpeer_ie *mp) + struct ieee80211_meshpeer_ie *mp, uint8_t subtype) { struct ieee80211vap *vap = ni->ni_vap; const struct ieee80211_meshpeer_ie *mpie; - const uint8_t *meshid, *meshconf, *meshpeerver, *meshpeer; + const uint8_t *meshid, *meshconf, *meshpeer; - meshid = meshconf = meshpeerver = meshpeer = NULL; + meshid = meshconf = meshpeer = NULL; while (efrm - frm > 1) { IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return NULL); switch (*frm) { - case IEEE80211_ELEMID_MESHPEERVER: - meshpeerver = frm; - break; case IEEE80211_ELEMID_MESHID: meshid = frm; break; @@ -1567,12 +1564,10 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni, meshpeer = frm; mpie = (const struct ieee80211_meshpeer_ie *) frm; memset(mp, 0, sizeof(*mp)); - mp->peer_subtype = mpie->peer_subtype; mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid); /* NB: peer link ID is optional on these frames */ - if (mpie->peer_subtype == - IEEE80211_MESH_PEER_LINK_CLOSE && - mpie->peer_len == 5) { + if (subtype == IEEE80211_MESH_PEER_LINK_CLOSE && + mpie->peer_len == 8) { mp->peer_linkid = 0; mp->peer_rcode = LE_READ_2(&mpie->peer_linkid); } else { @@ -1589,12 +1584,12 @@ mesh_parse_meshpeering_action(struct ieee80211_node *ni, * close subtype don't have a Mesh Configuration IE. * If if fails validation, close the peer link. */ - KASSERT(meshpeer != NULL && mp->peer_subtype != - IEEE80211_ACTION_MESHPEERING_CLOSE, ("parsing close action")); + KASSERT(meshpeer != NULL && + subtype != IEEE80211_ACTION_MESHPEERING_CLOSE, + ("parsing close action")); - if (mesh_verify_meshpeerver(vap, meshpeerver) || - mesh_verify_meshid(vap, meshid) || - mesh_verify_meshpeer(vap, meshpeer) || + if (mesh_verify_meshid(vap, meshid) || + mesh_verify_meshpeer(vap, subtype, meshpeer) || mesh_verify_meshconf(vap, meshconf)) { uint16_t args[3]; @@ -1638,7 +1633,8 @@ mesh_recv_action_meshpeering_open(struct ieee80211_node *ni, uint16_t args[3]; /* +2+2 for action + code + capabilites */ - meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie); + meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2, efrm, &ie, + IEEE80211_ACTION_MESHPEERING_OPEN); if (meshpeer == NULL) { return 0; } @@ -1770,7 +1766,8 @@ mesh_recv_action_meshpeering_confirm(struct ieee80211_node *ni, uint16_t args[3]; /* +2+2+2+2 for action + code + capabilites + status code + AID */ - meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie); + meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2+2+2+2, efrm, &ie, + IEEE80211_ACTION_MESHPEERING_CONFIRM); if (meshpeer == NULL) { return 0; } @@ -1933,7 +1930,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni, ic->ic_headroom + sizeof(struct ieee80211_frame), sizeof(uint16_t) /* action+category */ + sizeof(uint16_t) /* capabilites */ - + sizeof(struct ieee80211_meshpeerver_ie) + 2 + IEEE80211_RATE_SIZE + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + 2 + IEEE80211_MESHID_LEN @@ -1946,7 +1942,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni, * [1] category * [1] action * [2] capabilities - * [tlv] mesh peer protocol version * [tlv] rates * [tlv] xrates * [tlv] mesh id @@ -1956,7 +1951,6 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni, *frm++ = category; *frm++ = action; ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan)); - frm = ieee80211_add_meshpeerver(frm, vap); rs = ieee80211_get_suprates(ic, ic->ic_curchan); frm = ieee80211_add_rates(frm, rs); frm = ieee80211_add_xrates(frm, rs); @@ -1999,7 +1993,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni, + sizeof(uint16_t) /* capabilites */ + sizeof(uint16_t) /* status code */ + sizeof(uint16_t) /* AID */ - + sizeof(struct ieee80211_meshpeerver_ie) + 2 + IEEE80211_RATE_SIZE + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + 2 + IEEE80211_MESHID_LEN @@ -2014,7 +2007,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni, * [2] capabilities * [2] status code * [2] association id (peer ID) - * [tlv] mesh peer protocol version * [tlv] rates * [tlv] xrates * [tlv] mesh id @@ -2026,7 +2018,6 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni, ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan)); ADDSHORT(frm, 0); /* status code */ ADDSHORT(frm, args[1]); /* AID */ - frm = ieee80211_add_meshpeerver(frm, vap); rs = ieee80211_get_suprates(ic, ic->ic_curchan); frm = ieee80211_add_rates(frm, rs); frm = ieee80211_add_xrates(frm, rs); @@ -2067,7 +2058,6 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni, ic->ic_headroom + sizeof(struct ieee80211_frame), sizeof(uint16_t) /* action+category */ + sizeof(uint16_t) /* reason code */ - + sizeof(struct ieee80211_meshpeerver_ie) + 2 + IEEE80211_MESHID_LEN + sizeof(struct ieee80211_meshpeer_ie) ); @@ -2077,14 +2067,12 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni, * [1] category * [1] action * [2] reason code - * [tlv] mesh peer protocol version * [tlv] mesh id * [tlv] mesh peer link mgmt */ *frm++ = category; *frm++ = action; ADDSHORT(frm, args[2]); /* reason code */ - frm = ieee80211_add_meshpeerver(frm, vap); frm = ieee80211_add_meshid(frm, vap); frm = ieee80211_add_meshpeer(frm, IEEE80211_MESH_PEER_LINK_CLOSE, @@ -2278,19 +2266,6 @@ mesh_peer_timeout_cb(void *arg) } } -static int -mesh_verify_meshpeerver(struct ieee80211vap *vap, const uint8_t *ie) -{ - static const uint8_t peer[4] = IEEE80211_MESHPEERVER_PEER; - const struct ieee80211_meshpeerver_ie *meshpeerver = - (const struct ieee80211_meshpeerver_ie *) ie; - - if (meshpeerver->peerver_len != - sizeof(struct ieee80211_meshpeerver_ie) - 2) - return 1; - return memcmp(meshpeerver->peerver_proto, peer, 4); -} - static int mesh_verify_meshid(struct ieee80211vap *vap, const uint8_t *ie) { @@ -2364,26 +2339,28 @@ mesh_verify_meshconf(struct ieee80211vap *vap, const uint8_t *ie) } static int -mesh_verify_meshpeer(struct ieee80211vap *vap, const uint8_t *ie) +mesh_verify_meshpeer(struct ieee80211vap *vap, uint8_t subtype, + const uint8_t *ie) { const struct ieee80211_meshpeer_ie *meshpeer = (const struct ieee80211_meshpeer_ie *) ie; - if (meshpeer == NULL) + if (meshpeer == NULL || meshpeer->peer_len < 6 || + meshpeer->peer_len > 10) return 1; - switch (meshpeer->peer_subtype) { + switch (subtype) { case IEEE80211_MESH_PEER_LINK_OPEN: - if (meshpeer->peer_len != 3) + if (meshpeer->peer_len != 6) return 1; break; case IEEE80211_MESH_PEER_LINK_CONFIRM: - if (meshpeer->peer_len != 5) + if (meshpeer->peer_len != 8) return 1; break; case IEEE80211_MESH_PEER_LINK_CLOSE: - if (meshpeer->peer_len < 5) + if (meshpeer->peer_len < 8) return 1; - if (meshpeer->peer_len == 5 && meshpeer->peer_linkid != 0) + if (meshpeer->peer_len == 8 && meshpeer->peer_linkid != 0) return 1; if (meshpeer->peer_rcode == 0) return 1; @@ -2448,25 +2425,6 @@ ieee80211_add_meshconf(uint8_t *frm, struct ieee80211vap *vap) return frm; } -/* - * Add a Mesh Peer Protocol IE to a frame. - * XXX: needs to grow support for Abbreviated Handshake - */ -uint8_t * -ieee80211_add_meshpeerver(uint8_t *frm, struct ieee80211vap *vap) -{ - static struct ieee80211_meshpeerver_ie ie = { - .peerver_ie = IEEE80211_ELEMID_MESHPEERVER, - .peerver_len = 4, - .peerver_proto = IEEE80211_MESHPEERVER_PEER, - }; - - KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap")); - - memcpy(frm, &ie, sizeof(ie)); - return frm + sizeof(ie); -} - /* * Add a Mesh Peer Management IE to a frame. */ @@ -2474,28 +2432,34 @@ uint8_t * ieee80211_add_meshpeer(uint8_t *frm, uint8_t subtype, uint16_t localid, uint16_t peerid, uint16_t reason) { + /* XXX change for AH */ + static const uint8_t meshpeerproto[4] = IEEE80211_MESH_PEER_PROTO; + KASSERT(localid != 0, ("localid == 0")); *frm++ = IEEE80211_ELEMID_MESHPEER; switch (subtype) { case IEEE80211_MESH_PEER_LINK_OPEN: - *frm++ = 3; /* length */ - *frm++ = subtype; + *frm++ = 6; /* length */ + memcpy(frm, meshpeerproto, 4); + frm += 4; ADDSHORT(frm, localid); /* local ID */ break; case IEEE80211_MESH_PEER_LINK_CONFIRM: KASSERT(peerid != 0, ("sending peer confirm without peer id")); - *frm++ = 5; /* length */ - *frm++ = subtype; + *frm++ = 8; /* length */ + memcpy(frm, meshpeerproto, 4); + frm += 4; ADDSHORT(frm, localid); /* local ID */ ADDSHORT(frm, peerid); /* peer ID */ break; case IEEE80211_MESH_PEER_LINK_CLOSE: if (peerid) - *frm++ = 7; /* length */ + *frm++ = 10; /* length */ else - *frm++ = 5; /* length */ - *frm++ = subtype; + *frm++ = 8; /* length */ + memcpy(frm, meshpeerproto, 4); + frm += 4; ADDSHORT(frm, localid); /* local ID */ if (peerid) ADDSHORT(frm, peerid); /* peer ID */ diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index b02c257a5e52..e3ce79a4945e 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -34,7 +34,7 @@ #define IEEE80211_MESH_DEFAULT_TTL 31 /* - * NB: all structures are__packed so sizeof works on arm, et. al. + * NB: all structures are __packed so sizeof works on arm, et. al. */ /* * 802.11s Information Elements. @@ -116,28 +116,11 @@ struct ieee80211_meshcngst_ie { AC_BE, AC_VI, AC_VO */ } __packed; -/* Peer Version */ -struct ieee80211_meshpeerver_ie { - uint8_t peerver_ie; /* IEEE80211_ELEMID_MESHPEERVER */ - uint8_t peerver_len; - uint8_t peerver_proto[4]; -} __packed; -/* Mesh Peering Management Protocol */ -#define IEEE80211_MESHPEERVER_PEER_OUI 0x00, 0x0f, 0xac -#define IEEE80211_MESHPEERVER_PEER_VALUE 0x2a -#define IEEE80211_MESHPEERVER_PEER { IEEE80211_MESHPEERVER_PEER_OUI, \ - IEEE80211_MESHPEERVER_PEER_VALUE } -/* Abbreviated Handshake Protocol */ -#define IEEE80211_MESHPEERVER_AH_OUI 0x00, 0x0f, 0xac -#define IEEE80211_MESHPEERVER_AH_VALUE 0x2b -#define IEEE80211_MESHPEERVER_AH { IEEE80211_MESHPEERVER_AH_OUI, \ - IEEE80211_MESHPEERVER_AH_VALUE } - /* Peer Link Management */ struct ieee80211_meshpeer_ie { uint8_t peer_ie; /* IEEE80211_ELEMID_MESHPEER */ uint8_t peer_len; - uint8_t peer_subtype; + uint8_t peer_proto[4]; /* Peer Management Protocol */ uint16_t peer_llinkid; /* Local Link ID */ uint16_t peer_linkid; /* Peer Link ID */ uint16_t peer_rcode; @@ -150,6 +133,16 @@ enum { /* values 3-255 are reserved */ }; +/* Mesh Peering Management Protocol */ +#define IEEE80211_MESH_PEER_PROTO_OUI 0x00, 0x0f, 0xac +#define IEEE80211_MESH_PEER_PROTO_VALUE 0x2a +#define IEEE80211_MESH_PEER_PROTO { IEEE80211_MESH_PEER_PROTO_OUI, \ + IEEE80211_MESH_PEER_PROTO_VALUE } +/* Abbreviated Handshake Protocol */ +#define IEEE80211_MESH_PEER_PROTO_AH_OUI 0x00, 0x0f, 0xac +#define IEEE80211_MESH_PEER_PROTO_AH_VALUE 0x2b +#define IEEE80211_MESH_PEER_PROTO_AH { IEEE80211_MESH_PEER_PROTO_AH_OUI, \ + IEEE80211_MESH_PEER_PROTO_AH_VALUE } #ifdef notyet /* Mesh Channel Switch Annoucement */ struct ieee80211_meshcsa_ie { @@ -256,11 +249,15 @@ struct ieee80211_meshprep_ie { struct ieee80211_meshperr_ie { uint8_t perr_ie; /* IEEE80211_ELEMID_MESHPERR */ uint8_t perr_len; - uint8_t perr_mode; /* NB: reserved */ + uint8_t perr_ttl; uint8_t perr_ndests; /* Number of Destinations */ struct { + uint8_t dest_flags; +#define IEEE80211_MESHPERR_DFLAGS_USN 0x01 +#define IEEE80211_MESHPERR_DFLAGS_RC 0x02 uint8_t dest_addr[IEEE80211_ADDR_LEN]; uint32_t dest_seq; /* HWMP Sequence Number */ + uint16_t dest_rcode; } __packed perr_dests[1]; /* NB: variable size */ } __packed; @@ -310,14 +307,11 @@ enum { }; /* - * Mesh Path Selection Action codes. + * Mesh Path Selection Action code. */ enum { - IEEE80211_ACTION_MESHPATH_REQ = 0, - IEEE80211_ACTION_MESHPATH_REP = 1, - IEEE80211_ACTION_MESHPATH_ERR = 2, - IEEE80211_ACTION_MESHPATH_RANN = 3, - /* 4-255 reserved */ + IEEE80211_ACTION_MESHPATH_SEL = 0, + /* 1-255 reserved */ }; /* @@ -479,7 +473,6 @@ int ieee80211_mesh_register_proto_path(const int ieee80211_mesh_register_proto_metric(const struct ieee80211_mesh_proto_metric *); -uint8_t * ieee80211_add_meshpeerver(uint8_t *, struct ieee80211vap *); uint8_t * ieee80211_add_meshid(uint8_t *, struct ieee80211vap *); uint8_t * ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *); uint8_t * ieee80211_add_meshpeer(uint8_t *, uint8_t, uint16_t, uint16_t,