summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2012-03-06 21:20:16 +0000
committeradrian <adrian@FreeBSD.org>2012-03-06 21:20:16 +0000
commit2960bf1153624ff5f817f866e4b2a91c057a7bf4 (patch)
treeb5ca85b3a41a01dd6dac50ebcff29e4fd5988f9f /sys/net80211
parent13aacec1f8c622aee729b991194b07b3ab64b7e9 (diff)
downloadFreeBSD-src-2960bf1153624ff5f817f866e4b2a91c057a7bf4.zip
FreeBSD-src-2960bf1153624ff5f817f866e4b2a91c057a7bf4.tar.gz
Modify HWMP to be able to allocate memory for PREQ/PREP/PERR for all scenarios.
* Added verify_mesh_*_len functions that verify the length according to the amendment spec and return number of destination addresses for allocation of appropriate struct size in memory; * Modified hwmp_recv_action_meshpath to allocate HWMP ie instead of storing them on the stack and store all available field according the flags; * Modify hwmp_add_mesh* to work with all cases of HWMP according to amendment. * Modify hwmp_send_* to calculate correct len of bytes for the HWMP ie. * Added new M_80211_MESH_* malloc defines. * Added macros with magic numbers for HWMP ie sizes according to amendment. * Added the external address to all HWMP ie structs. Submitted by: monthadar@gmail.com
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_hwmp.c338
-rw-r--r--sys/net80211/ieee80211_mesh.c4
-rw-r--r--sys/net80211/ieee80211_mesh.h32
3 files changed, 305 insertions, 69 deletions
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index d084c5f..ff49d9e 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -279,17 +279,114 @@ hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
return 0;
}
+/*
+ * Verify the length of an HWMP PREQ and return the number
+ * of destinations >= 1, if verification fails -1 is returned.
+ */
+static int
+verify_mesh_preq_len(struct ieee80211vap *vap,
+ const struct ieee80211_frame *wh, const uint8_t *iefrm)
+{
+ int alloc_sz = -1;
+ int ndest = -1;
+ if (iefrm[2] & IEEE80211_MESHPREQ_FLAGS_AE) {
+ /* Originator External Address present */
+ alloc_sz = IEEE80211_MESHPREQ_BASE_SZ_AE;
+ ndest = iefrm[IEEE80211_MESHPREQ_TCNT_OFFSET_AE];
+ } else {
+ /* w/o Originator External Address */
+ alloc_sz = IEEE80211_MESHPREQ_BASE_SZ;
+ ndest = iefrm[IEEE80211_MESHPREQ_TCNT_OFFSET];
+ }
+ alloc_sz += ndest * IEEE80211_MESHPREQ_TRGT_SZ;
+
+ if(iefrm[1] != (alloc_sz)) {
+ IEEE80211_DISCARD(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
+ wh, NULL, "PREQ (AE=%s) with wrong len",
+ iefrm[2] & IEEE80211_MESHPREQ_FLAGS_AE ? "1" : "0");
+ return (-1);
+ }
+ return ndest;
+}
+
+/*
+ * Verify the length of an HWMP PREP and returns 1 on success,
+ * otherwise -1.
+ */
+static int
+verify_mesh_prep_len(struct ieee80211vap *vap,
+ const struct ieee80211_frame *wh, const uint8_t *iefrm)
+{
+ int alloc_sz = -1;
+ if (iefrm[2] & IEEE80211_MESHPREP_FLAGS_AE) {
+ if (iefrm[1] == IEEE80211_MESHPREP_BASE_SZ_AE)
+ alloc_sz = IEEE80211_MESHPREP_BASE_SZ_AE;
+ } else if (iefrm[1] == IEEE80211_MESHPREP_BASE_SZ)
+ alloc_sz = IEEE80211_MESHPREP_BASE_SZ;
+ if(alloc_sz < 0) {
+ IEEE80211_DISCARD(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
+ wh, NULL, "PREP (AE=%s) with wrong len",
+ iefrm[2] & IEEE80211_MESHPREP_FLAGS_AE ? "1" : "0");
+ return (-1);
+ }
+ return (1);
+}
+
+/*
+ * Verify the length of an HWMP PERR and return the number
+ * of destinations >= 1, if verification fails -1 is returned.
+ */
+static int
+verify_mesh_perr_len(struct ieee80211vap *vap,
+ const struct ieee80211_frame *wh, const uint8_t *iefrm)
+{
+ int alloc_sz = -1;
+ const uint8_t *iefrm_t = iefrm;
+ uint8_t ndest = iefrm_t[IEEE80211_MESHPERR_NDEST_OFFSET];
+ int i;
+
+ if(ndest > IEEE80211_MESHPERR_MAXDEST) {
+ IEEE80211_DISCARD(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
+ wh, NULL, "PERR with wrong number of destionat (>19), %u",
+ ndest);
+ return (-1);
+ }
+
+ iefrm_t += IEEE80211_MESHPERR_NDEST_OFFSET + 1; /* flag is next field */
+ /* We need to check each destionation flag to know size */
+ for(i = 0; i<ndest; i++) {
+ if ((*iefrm_t) & IEEE80211_MESHPERR_FLAGS_AE)
+ iefrm_t += IEEE80211_MESHPERR_DEST_SZ_AE;
+ else
+ iefrm_t += IEEE80211_MESHPERR_DEST_SZ;
+ }
+
+ alloc_sz = (iefrm_t - iefrm) - 2; /* action + code */
+ if(alloc_sz != iefrm[1]) {
+ IEEE80211_DISCARD(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
+ wh, NULL, "%s", "PERR with wrong len");
+ return (-1);
+ }
+ return ndest;
+}
+
static int
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_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 */
+ const uint8_t *iefrm_t = iefrm; /* temporary pointer */
+ int ndest = -1;
int found = 0;
while (efrm - iefrm > 1) {
@@ -297,66 +394,132 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
switch (*iefrm) {
case IEEE80211_ELEMID_MESHPREQ:
{
- const struct ieee80211_meshpreq_ie *mpreq =
- (const struct ieee80211_meshpreq_ie *) iefrm;
- /* XXX > 1 target */
- if (mpreq->preq_len !=
- sizeof(struct ieee80211_meshpreq_ie) - 2) {
- IEEE80211_DISCARD(vap,
- IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
- wh, NULL, "%s", "PREQ with wrong len");
+ int i = 0;
+
+ iefrm_t = iefrm;
+ ndest = verify_mesh_preq_len(vap, wh, iefrm_t);
+ if (ndest < 0) {
vap->iv_stats.is_rx_mgtdiscard++;
break;
}
- memcpy(&preq, mpreq, sizeof(preq));
- preq.preq_id = LE_READ_4(&mpreq->preq_id);
- preq.preq_origseq = LE_READ_4(&mpreq->preq_origseq);
- preq.preq_lifetime = LE_READ_4(&mpreq->preq_lifetime);
- preq.preq_metric = LE_READ_4(&mpreq->preq_metric);
- preq.preq_targets[0].target_seq =
- LE_READ_4(&mpreq->preq_targets[0].target_seq);
- hwmp_recv_preq(vap, ni, wh, &preq);
+ preq = malloc(sizeof(*preq) +
+ (ndest - 1) * sizeof(*preq->preq_targets),
+ M_80211_MESH_PREQ, M_NOWAIT | M_ZERO);
+ KASSERT(preq != NULL, ("preq == NULL"));
+
+ preq->preq_ie = *iefrm_t++;
+ preq->preq_len = *iefrm_t++;
+ preq->preq_flags = *iefrm_t++;
+ preq->preq_hopcount = *iefrm_t++;
+ preq->preq_ttl = *iefrm_t++;
+ preq->preq_id = LE_READ_4(iefrm_t); iefrm_t += 4;
+ IEEE80211_ADDR_COPY(preq->preq_origaddr, iefrm_t);
+ iefrm_t += 6;
+ preq->preq_origseq = LE_READ_4(iefrm_t); iefrm_t += 4;
+ /* NB: may have Originator Proxied Address */
+ if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE) {
+ IEEE80211_ADDR_COPY(
+ preq->preq_orig_ext_addr, iefrm_t);
+ iefrm_t += 6;
+ }
+ preq->preq_lifetime = LE_READ_4(iefrm_t); iefrm_t += 4;
+ preq->preq_metric = LE_READ_4(iefrm_t); iefrm_t += 4;
+ preq->preq_tcount = *iefrm_t++;
+
+ for (i = 0; i < preq->preq_tcount; i++) {
+ preq->preq_targets[i].target_flags = *iefrm_t++;
+ IEEE80211_ADDR_COPY(
+ preq->preq_targets[i].target_addr, iefrm_t);
+ iefrm_t += 6;
+ preq->preq_targets[i].target_seq =
+ LE_READ_4(iefrm_t);
+ iefrm_t += 4;
+ }
+
+ hwmp_recv_preq(vap, ni, wh, preq);
+ free(preq, M_80211_MESH_PREQ);
found++;
- break;
+ break;
}
case IEEE80211_ELEMID_MESHPREP:
{
- const struct ieee80211_meshprep_ie *mprep =
- (const struct ieee80211_meshprep_ie *) iefrm;
- if (mprep->prep_len !=
- sizeof(struct ieee80211_meshprep_ie) - 2) {
- IEEE80211_DISCARD(vap,
- IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
- wh, NULL, "%s", "PREP with wrong len");
+ iefrm_t = iefrm;
+ ndest = verify_mesh_prep_len(vap, wh, iefrm_t);
+ if (ndest < 0) {
vap->iv_stats.is_rx_mgtdiscard++;
break;
}
- memcpy(&prep, mprep, sizeof(prep));
- prep.prep_targetseq = LE_READ_4(&mprep->prep_targetseq);
- prep.prep_lifetime = LE_READ_4(&mprep->prep_lifetime);
- 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);
+ prep = malloc(sizeof(*prep),
+ M_80211_MESH_PREP, M_NOWAIT | M_ZERO);
+ KASSERT(prep != NULL, ("prep == NULL"));
+
+ prep->prep_ie = *iefrm_t++;
+ prep->prep_len = *iefrm_t++;
+ prep->prep_flags = *iefrm_t++;
+ prep->prep_hopcount = *iefrm_t++;
+ prep->prep_ttl = *iefrm_t++;
+ IEEE80211_ADDR_COPY(prep->prep_targetaddr, iefrm_t);
+ iefrm_t += 6;
+ prep->prep_targetseq = LE_READ_4(iefrm_t); iefrm_t += 4;
+ /* NB: May have Target Proxied Address */
+ if (prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE) {
+ IEEE80211_ADDR_COPY(
+ prep->prep_target_ext_addr, iefrm_t);
+ iefrm_t += 6;
+ }
+ prep->prep_lifetime = LE_READ_4(iefrm_t); iefrm_t += 4;
+ prep->prep_metric = LE_READ_4(iefrm_t); iefrm_t += 4;
+ IEEE80211_ADDR_COPY(prep->prep_origaddr, iefrm_t);
+ iefrm_t += 6;
+ prep->prep_origseq = LE_READ_4(iefrm_t); iefrm_t += 4;
+
+ hwmp_recv_prep(vap, ni, wh, prep);
+ free(prep, M_80211_MESH_PREP);
found++;
break;
}
case IEEE80211_ELEMID_MESHPERR:
{
- const struct ieee80211_meshperr_ie *mperr =
- (const struct ieee80211_meshperr_ie *) iefrm;
- /* XXX > 1 target */
- if (mperr->perr_len !=
- sizeof(struct ieee80211_meshperr_ie) - 2) {
- IEEE80211_DISCARD(vap,
- IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
- wh, NULL, "%s", "PERR with wrong len");
+ int i = 0;
+
+ iefrm_t = iefrm;
+ ndest = verify_mesh_perr_len(vap, wh, iefrm_t);
+ if (ndest < 0) {
vap->iv_stats.is_rx_mgtdiscard++;
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);
+ perr = malloc(sizeof(*perr) +
+ (ndest - 1) * sizeof(*perr->perr_dests),
+ M_80211_MESH_PERR, M_NOWAIT | M_ZERO);
+ KASSERT(perr != NULL, ("perr == NULL"));
+
+ perr->perr_ie = *iefrm_t++;
+ perr->perr_len = *iefrm_t++;
+ perr->perr_ttl = *iefrm_t++;
+ perr->perr_ndests = *iefrm_t++;
+
+ for (i = 0; i<perr->perr_ndests; i++) {
+ perr->perr_dests[i].dest_flags = *iefrm_t++;
+ IEEE80211_ADDR_COPY(
+ perr->perr_dests[i].dest_addr, iefrm_t);
+ iefrm_t += 6;
+ perr->perr_dests[i].dest_seq = LE_READ_4(iefrm_t);
+ iefrm_t += 4;
+ /* NB: May have Target Proxied Address */
+ if (perr->perr_dests[i].dest_flags &
+ IEEE80211_MESHPERR_FLAGS_AE) {
+ IEEE80211_ADDR_COPY(
+ perr->perr_dests[i].dest_ext_addr,
+ iefrm_t);
+ iefrm_t += 6;
+ }
+ perr->perr_dests[i].dest_rcode =
+ LE_READ_2(iefrm_t);
+ iefrm_t += 2;
+ }
+
+ hwmp_recv_perr(vap, ni, wh, perr);
+ free(perr, M_80211_MESH_PERR);
found++;
break;
}
@@ -369,7 +532,7 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni,
IEEE80211_DISCARD(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP,
wh, NULL, "%s", "RAN with wrong len");
- vap->iv_stats.is_rx_mgtdiscard++;
+ vap->iv_stats.is_rx_mgtdiscard++;
return 1;
}
memcpy(&rann, mrann, sizeof(rann));
@@ -492,31 +655,40 @@ hwmp_send_action(struct ieee80211_node *ni,
/*
* Add a Mesh Path Request IE to a frame.
*/
+#define PREQ_TFLAGS(n) preq->preq_targets[n].target_flags
+#define PREQ_TADDR(n) preq->preq_targets[n].target_addr
+#define PREQ_TSEQ(n) preq->preq_targets[n].target_seq
static uint8_t *
hwmp_add_meshpreq(uint8_t *frm, const struct ieee80211_meshpreq_ie *preq)
{
int i;
*frm++ = IEEE80211_ELEMID_MESHPREQ;
- *frm++ = sizeof(struct ieee80211_meshpreq_ie) - 2 +
- (preq->preq_tcount - 1) * sizeof(*preq->preq_targets);
+ *frm++ = preq->preq_len; /* len already calculated */
*frm++ = preq->preq_flags;
*frm++ = preq->preq_hopcount;
*frm++ = preq->preq_ttl;
ADDWORD(frm, preq->preq_id);
IEEE80211_ADDR_COPY(frm, preq->preq_origaddr); frm += 6;
ADDWORD(frm, preq->preq_origseq);
+ if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE) {
+ IEEE80211_ADDR_COPY(frm, preq->preq_orig_ext_addr);
+ frm += 6;
+ }
ADDWORD(frm, preq->preq_lifetime);
ADDWORD(frm, preq->preq_metric);
*frm++ = preq->preq_tcount;
for (i = 0; i < preq->preq_tcount; i++) {
- *frm++ = preq->preq_targets[i].target_flags;
- IEEE80211_ADDR_COPY(frm, preq->preq_targets[i].target_addr);
+ *frm++ = PREQ_TFLAGS(i);
+ IEEE80211_ADDR_COPY(frm, PREQ_TADDR(i));
frm += 6;
- ADDWORD(frm, preq->preq_targets[i].target_seq);
+ ADDWORD(frm, PREQ_TSEQ(i));
}
return frm;
}
+#undef PREQ_TFLAGS
+#undef PREQ_TADDR
+#undef PREQ_TSEQ
/*
* Add a Mesh Path Reply IE to a frame.
@@ -525,12 +697,16 @@ static uint8_t *
hwmp_add_meshprep(uint8_t *frm, const struct ieee80211_meshprep_ie *prep)
{
*frm++ = IEEE80211_ELEMID_MESHPREP;
- *frm++ = sizeof(struct ieee80211_meshprep_ie) - 2;
+ *frm++ = prep->prep_len; /* len already calculated */
*frm++ = prep->prep_flags;
*frm++ = prep->prep_hopcount;
*frm++ = prep->prep_ttl;
IEEE80211_ADDR_COPY(frm, prep->prep_targetaddr); frm += 6;
ADDWORD(frm, prep->prep_targetseq);
+ if (prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE) {
+ IEEE80211_ADDR_COPY(frm, prep->prep_target_ext_addr);
+ frm += 6;
+ }
ADDWORD(frm, prep->prep_lifetime);
ADDWORD(frm, prep->prep_metric);
IEEE80211_ADDR_COPY(frm, prep->prep_origaddr); frm += 6;
@@ -541,25 +717,38 @@ hwmp_add_meshprep(uint8_t *frm, const struct ieee80211_meshprep_ie *prep)
/*
* Add a Mesh Path Error IE to a frame.
*/
+#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_EXTADDR(n) perr->perr_dests[n].dest_ext_addr
+#define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode
static uint8_t *
hwmp_add_meshperr(uint8_t *frm, const struct ieee80211_meshperr_ie *perr)
{
int i;
*frm++ = IEEE80211_ELEMID_MESHPERR;
- *frm++ = sizeof(struct ieee80211_meshperr_ie) - 2 +
- (perr->perr_ndests - 1) * sizeof(*perr->perr_dests);
+ *frm++ = perr->perr_len; /* len already calculated */
*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++ = PERR_DFLAGS(i);
+ IEEE80211_ADDR_COPY(frm, PERR_DADDR(i));
frm += 6;
- ADDWORD(frm, perr->perr_dests[i].dest_seq);
- ADDSHORT(frm, perr->perr_dests[i].dest_rcode);
+ ADDWORD(frm, PERR_DSEQ(i));
+ if (PERR_DFLAGS(i) & IEEE80211_MESHPERR_FLAGS_AE) {
+ IEEE80211_ADDR_COPY(frm, PERR_EXTADDR(i));
+ frm += 6;
+ }
+ ADDSHORT(frm, PERR_DRCODE(i));
}
return frm;
}
+#undef PERR_DFLAGS
+#undef PERR_DADDR
+#undef PERR_DSEQ
+#undef PERR_EXTADDR
+#undef PERR_DRCODE
/*
* Add a Root Annoucement IE to a frame.
@@ -568,12 +757,13 @@ static uint8_t *
hwmp_add_meshrann(uint8_t *frm, const struct ieee80211_meshrann_ie *rann)
{
*frm++ = IEEE80211_ELEMID_MESHRANN;
- *frm++ = sizeof(struct ieee80211_meshrann_ie) - 2;
+ *frm++ = rann->rann_len;
*frm++ = rann->rann_flags;
*frm++ = rann->rann_hopcount;
*frm++ = rann->rann_ttl;
IEEE80211_ADDR_COPY(frm, rann->rann_addr); frm += 6;
ADDWORD(frm, rann->rann_seq);
+ ADDWORD(frm, rann->rann_interval);
ADDWORD(frm, rann->rann_metric);
return frm;
}
@@ -980,8 +1170,10 @@ hwmp_send_preq(struct ieee80211_node *ni,
* [tlv] mesh path request
*/
preq->preq_ie = IEEE80211_ELEMID_MESHPREQ;
- return hwmp_send_action(ni, sa, da, (uint8_t *)preq,
- sizeof(struct ieee80211_meshpreq_ie));
+ preq->preq_len = (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE ?
+ IEEE80211_MESHPREQ_BASE_SZ_AE : IEEE80211_MESHPREQ_BASE_SZ) +
+ preq->preq_tcount * IEEE80211_MESHPREQ_TRGT_SZ;
+ return hwmp_send_action(ni, sa, da, (uint8_t *)preq, preq->preq_len+2);
}
static void
@@ -1162,8 +1354,10 @@ hwmp_send_prep(struct ieee80211_node *ni,
* [tlv] mesh path reply
*/
prep->prep_ie = IEEE80211_ELEMID_MESHPREP;
+ prep->prep_len = prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE ?
+ IEEE80211_MESHPREP_BASE_SZ_AE : IEEE80211_MESHPREP_BASE_SZ;
return hwmp_send_action(ni, sa, da, (uint8_t *)prep,
- sizeof(struct ieee80211_meshprep_ie));
+ prep->prep_len + 2);
}
#define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags
@@ -1254,8 +1448,10 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni,
&pperr);
}
}
+#undef PERR_DFLAGS
#undef PEER_DADDR
#undef PERR_DSEQ
+#undef PERR_DRCODE
static int
hwmp_send_perr(struct ieee80211_node *ni,
@@ -1264,6 +1460,8 @@ hwmp_send_perr(struct ieee80211_node *ni,
struct ieee80211_meshperr_ie *perr)
{
struct ieee80211_hwmp_state *hs = ni->ni_vap->iv_hwmp;
+ int i;
+ uint8_t length = 0;
/*
* Enforce PERR interval.
@@ -1282,8 +1480,17 @@ hwmp_send_perr(struct ieee80211_node *ni,
* [tlv] mesh path error
*/
perr->perr_ie = IEEE80211_ELEMID_MESHPERR;
- return hwmp_send_action(ni, sa, da, (uint8_t *)perr,
- sizeof(struct ieee80211_meshperr_ie));
+ length = IEEE80211_MESHPERR_BASE_SZ;
+ for (i = 0; i<perr->perr_ndests; i++) {
+ if (perr->perr_dests[i].dest_flags &
+ IEEE80211_MESHPERR_FLAGS_AE) {
+ length += IEEE80211_MESHPERR_DEST_SZ_AE;
+ continue ;
+ }
+ length += IEEE80211_MESHPERR_DEST_SZ;
+ }
+ perr->perr_len =length;
+ return hwmp_send_action(ni, sa, da, (uint8_t *)perr, perr->perr_len+2);
}
static void
@@ -1342,8 +1549,9 @@ hwmp_send_rann(struct ieee80211_node *ni,
* [tlv] root annoucement
*/
rann->rann_ie = IEEE80211_ELEMID_MESHRANN;
+ rann->rann_len = IEEE80211_MESHRANN_BASE_SZ;
return hwmp_send_action(ni, sa, da, (uint8_t *)rann,
- sizeof(struct ieee80211_meshrann_ie));
+ rann->rann_len + 2);
}
#define PREQ_TFLAGS(n) preq.preq_targets[n].target_flags
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index 576e20b..53addfb 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -142,6 +142,10 @@ static struct ieee80211_mesh_proto_metric mesh_proto_metrics[4];
#define MESH_RT_LOCK_ASSERT(ms) mtx_assert(&(ms)->ms_rt_lock, MA_OWNED)
#define MESH_RT_UNLOCK(ms) mtx_unlock(&(ms)->ms_rt_lock)
+MALLOC_DEFINE(M_80211_MESH_PREQ, "80211preq", "802.11 MESH Path Request frame");
+MALLOC_DEFINE(M_80211_MESH_PREP, "80211prep", "802.11 MESH Path Reply frame");
+MALLOC_DEFINE(M_80211_MESH_PERR, "80211perr", "802.11 MESH Path Error frame");
+
MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table");
/*
diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h
index fde8859..58d7608 100644
--- a/sys/net80211/ieee80211_mesh.h
+++ b/sys/net80211/ieee80211_mesh.h
@@ -212,6 +212,7 @@ struct ieee80211_meshpann_ie {
} __packed;
/* Root (MP) Annoucement */
+#define IEEE80211_MESHRANN_BASE_SZ (21)
struct ieee80211_meshrann_ie {
uint8_t rann_ie; /* IEEE80211_ELEMID_MESHRANN */
uint8_t rann_len;
@@ -221,10 +222,16 @@ struct ieee80211_meshrann_ie {
uint8_t rann_ttl;
uint8_t rann_addr[IEEE80211_ADDR_LEN];
uint32_t rann_seq; /* HWMP Sequence Number */
+ uint32_t rann_interval;
uint32_t rann_metric;
} __packed;
/* Mesh Path Request */
+#define IEEE80211_MESHPREQ_BASE_SZ (26)
+#define IEEE80211_MESHPREQ_BASE_SZ_AE (32)
+#define IEEE80211_MESHPREQ_TRGT_SZ (11)
+#define IEEE80211_MESHPREQ_TCNT_OFFSET (27)
+#define IEEE80211_MESHPREQ_TCNT_OFFSET_AE (33)
struct ieee80211_meshpreq_ie {
uint8_t preq_ie; /* IEEE80211_ELEMID_MESHPREQ */
uint8_t preq_len;
@@ -238,7 +245,8 @@ struct ieee80211_meshpreq_ie {
uint32_t preq_id;
uint8_t preq_origaddr[IEEE80211_ADDR_LEN];
uint32_t preq_origseq; /* HWMP Sequence Number */
- /* NB: may have Originator Proxied Address */
+ /* NB: may have Originator External Address */
+ uint8_t preq_orig_ext_addr[IEEE80211_ADDR_LEN];
uint32_t preq_lifetime;
uint32_t preq_metric;
uint8_t preq_tcount; /* target count */
@@ -253,15 +261,19 @@ struct ieee80211_meshpreq_ie {
} __packed;
/* Mesh Path Reply */
+#define IEEE80211_MESHPREP_BASE_SZ (31)
+#define IEEE80211_MESHPREP_BASE_SZ_AE (37)
struct ieee80211_meshprep_ie {
uint8_t prep_ie; /* IEEE80211_ELEMID_MESHPREP */
uint8_t prep_len;
uint8_t prep_flags;
+#define IEEE80211_MESHPREP_FLAGS_AE 0x40 /* Address Extension */
uint8_t prep_hopcount;
uint8_t prep_ttl;
uint8_t prep_targetaddr[IEEE80211_ADDR_LEN];
uint32_t prep_targetseq;
- /* NB: May have Target Proxied Address */
+ /* NB: May have Target External Address */
+ uint8_t prep_target_ext_addr[IEEE80211_ADDR_LEN];
uint32_t prep_lifetime;
uint32_t prep_metric;
uint8_t prep_origaddr[IEEE80211_ADDR_LEN];
@@ -269,6 +281,11 @@ struct ieee80211_meshprep_ie {
} __packed;
/* Mesh Path Error */
+#define IEEE80211_MESHPERR_MAXDEST (19)
+#define IEEE80211_MESHPERR_NDEST_OFFSET (3)
+#define IEEE80211_MESHPERR_BASE_SZ (2)
+#define IEEE80211_MESHPERR_DEST_SZ (13)
+#define IEEE80211_MESHPERR_DEST_SZ_AE (19)
struct ieee80211_meshperr_ie {
uint8_t perr_ie; /* IEEE80211_ELEMID_MESHPERR */
uint8_t perr_len;
@@ -276,10 +293,13 @@ struct ieee80211_meshperr_ie {
uint8_t perr_ndests; /* Number of Destinations */
struct {
uint8_t dest_flags;
-#define IEEE80211_MESHPERR_DFLAGS_USN 0x01
-#define IEEE80211_MESHPERR_DFLAGS_RC 0x02
+#define IEEE80211_MESHPERR_DFLAGS_USN 0x01 /* XXX: not part of standard */
+#define IEEE80211_MESHPERR_DFLAGS_RC 0x02 /* XXX: not part of standard */
+#define IEEE80211_MESHPERR_FLAGS_AE 0x40 /* Address Extension */
uint8_t dest_addr[IEEE80211_ADDR_LEN];
uint32_t dest_seq; /* HWMP Sequence Number */
+ /* NB: May have Destination External Address */
+ uint8_t dest_ext_addr[IEEE80211_ADDR_LEN];
uint16_t dest_rcode;
} __packed perr_dests[1]; /* NB: variable size */
} __packed;
@@ -390,6 +410,10 @@ struct ieee80211_meshcntl_ae11 {
} __packed;
#ifdef _KERNEL
+MALLOC_DECLARE(M_80211_MESH_PREQ);
+MALLOC_DECLARE(M_80211_MESH_PREP);
+MALLOC_DECLARE(M_80211_MESH_PERR);
+
MALLOC_DECLARE(M_80211_MESH_RT);
struct ieee80211_mesh_route {
TAILQ_ENTRY(ieee80211_mesh_route) rt_next;
OpenPOWER on IntegriCloud