1 /*- 2 * Copyright (c) 2009 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Rui Paulo under sponsorship from the 6 * FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 #include <sys/cdefs.h> 30 #ifdef __FreeBSD__ 31 __FBSDID("$FreeBSD$"); 32 #endif 33 34 /* 35 * IEEE 802.11s Hybrid Wireless Mesh Protocol, HWMP. 36 * 37 * Based on March 2009, D3.0 802.11s draft spec. 38 */ 39 #include "opt_inet.h" 40 #include "opt_wlan.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/mbuf.h> 45 #include <sys/malloc.h> 46 #include <sys/kernel.h> 47 48 #include <sys/socket.h> 49 #include <sys/sockio.h> 50 #include <sys/endian.h> 51 #include <sys/errno.h> 52 #include <sys/proc.h> 53 #include <sys/sysctl.h> 54 55 #include <net/if.h> 56 #include <net/if_media.h> 57 #include <net/if_llc.h> 58 #include <net/ethernet.h> 59 60 #include <net/bpf.h> 61 62 #include <net80211/ieee80211_var.h> 63 #include <net80211/ieee80211_action.h> 64 #include <net80211/ieee80211_input.h> 65 #include <net80211/ieee80211_mesh.h> 66 67 static void hwmp_vattach(struct ieee80211vap *); 68 static void hwmp_vdetach(struct ieee80211vap *); 69 static int hwmp_newstate(struct ieee80211vap *, 70 enum ieee80211_state, int); 71 static int hwmp_send_action(struct ieee80211_node *, 72 const uint8_t [IEEE80211_ADDR_LEN], 73 const uint8_t [IEEE80211_ADDR_LEN], 74 uint8_t *, size_t); 75 static uint8_t * hwmp_add_meshpreq(uint8_t *, 76 const struct ieee80211_meshpreq_ie *); 77 static uint8_t * hwmp_add_meshprep(uint8_t *, 78 const struct ieee80211_meshprep_ie *); 79 static uint8_t * hwmp_add_meshperr(uint8_t *, 80 const struct ieee80211_meshperr_ie *); 81 static uint8_t * hwmp_add_meshrann(uint8_t *, 82 const struct ieee80211_meshrann_ie *); 83 static void hwmp_rootmode_setup(struct ieee80211vap *); 84 static void hwmp_rootmode_cb(void *); 85 static void hwmp_rootmode_rann_cb(void *); 86 static void hwmp_recv_preq(struct ieee80211vap *, struct ieee80211_node *, 87 const struct ieee80211_frame *, 88 const struct ieee80211_meshpreq_ie *); 89 static int hwmp_send_preq(struct ieee80211_node *, 90 const uint8_t [IEEE80211_ADDR_LEN], 91 const uint8_t [IEEE80211_ADDR_LEN], 92 struct ieee80211_meshpreq_ie *); 93 static void hwmp_recv_prep(struct ieee80211vap *, struct ieee80211_node *, 94 const struct ieee80211_frame *, 95 const struct ieee80211_meshprep_ie *); 96 static int hwmp_send_prep(struct ieee80211_node *, 97 const uint8_t [IEEE80211_ADDR_LEN], 98 const uint8_t [IEEE80211_ADDR_LEN], 99 struct ieee80211_meshprep_ie *); 100 static void hwmp_recv_perr(struct ieee80211vap *, struct ieee80211_node *, 101 const struct ieee80211_frame *, 102 const struct ieee80211_meshperr_ie *); 103 static int hwmp_send_perr(struct ieee80211_node *, 104 const uint8_t [IEEE80211_ADDR_LEN], 105 const uint8_t [IEEE80211_ADDR_LEN], 106 struct ieee80211_meshperr_ie *); 107 static void hwmp_recv_rann(struct ieee80211vap *, struct ieee80211_node *, 108 const struct ieee80211_frame *, 109 const struct ieee80211_meshrann_ie *); 110 static int hwmp_send_rann(struct ieee80211_node *, 111 const uint8_t [IEEE80211_ADDR_LEN], 112 const uint8_t [IEEE80211_ADDR_LEN], 113 struct ieee80211_meshrann_ie *); 114 static struct ieee80211_node * 115 hwmp_discover(struct ieee80211vap *, 116 const uint8_t [IEEE80211_ADDR_LEN], struct mbuf *); 117 static void hwmp_peerdown(struct ieee80211_node *); 118 119 static struct timeval ieee80211_hwmp_preqminint = { 0, 100000 }; 120 static struct timeval ieee80211_hwmp_perrminint = { 0, 100000 }; 121 122 /* unalligned little endian access */ 123 #define LE_WRITE_2(p, v) do { \ 124 ((uint8_t *)(p))[0] = (v) & 0xff; \ 125 ((uint8_t *)(p))[1] = ((v) >> 8) & 0xff; \ 126 } while (0) 127 #define LE_WRITE_4(p, v) do { \ 128 ((uint8_t *)(p))[0] = (v) & 0xff; \ 129 ((uint8_t *)(p))[1] = ((v) >> 8) & 0xff; \ 130 ((uint8_t *)(p))[2] = ((v) >> 16) & 0xff; \ 131 ((uint8_t *)(p))[3] = ((v) >> 24) & 0xff; \ 132 } while (0) 133 134 135 /* NB: the Target Address set in a Proactive PREQ is the broadcast address. */ 136 static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] = 137 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 138 139 typedef uint32_t ieee80211_hwmp_seq; 140 #define HWMP_SEQ_LT(a, b) ((int32_t)((a)-(b)) < 0) 141 #define HWMP_SEQ_LEQ(a, b) ((int32_t)((a)-(b)) <= 0) 142 #define HWMP_SEQ_EQ(a, b) ((int32_t)((a)-(b)) == 0) 143 #define HWMP_SEQ_GT(a, b) ((int32_t)((a)-(b)) > 0) 144 #define HWMP_SEQ_GEQ(a, b) ((int32_t)((a)-(b)) >= 0) 145 146 /* The longer one of the lifetime should be stored as new lifetime */ 147 #define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b) 148 149 /* 150 * Private extension of ieee80211_mesh_route. 151 */ 152 struct ieee80211_hwmp_route { 153 ieee80211_hwmp_seq hr_seq; /* last HWMP seq seen from dst*/ 154 ieee80211_hwmp_seq hr_preqid; /* last PREQ ID seen from dst */ 155 ieee80211_hwmp_seq hr_origseq; /* seq. no. on our latest PREQ*/ 156 int hr_preqretries; 157 }; 158 struct ieee80211_hwmp_state { 159 ieee80211_hwmp_seq hs_seq; /* next seq to be used */ 160 ieee80211_hwmp_seq hs_preqid; /* next PREQ ID to be used */ 161 struct timeval hs_lastpreq; /* last time we sent a PREQ */ 162 struct timeval hs_lastperr; /* last time we sent a PERR */ 163 int hs_rootmode; /* proactive HWMP */ 164 struct callout hs_roottimer; 165 uint8_t hs_maxhops; /* max hop count */ 166 }; 167 168 static SYSCTL_NODE(_net_wlan, OID_AUTO, hwmp, CTLFLAG_RD, 0, 169 "IEEE 802.11s HWMP parameters"); 170 static int ieee80211_hwmp_targetonly = 0; 171 SYSCTL_INT(_net_wlan_hwmp, OID_AUTO, targetonly, CTLTYPE_INT | CTLFLAG_RW, 172 &ieee80211_hwmp_targetonly, 0, "Set TO bit on generated PREQs"); 173 static int ieee80211_hwmp_replyforward = 1; 174 SYSCTL_INT(_net_wlan_hwmp, OID_AUTO, replyforward, CTLTYPE_INT | CTLFLAG_RW, 175 &ieee80211_hwmp_replyforward, 0, "Set RF bit on generated PREQs"); 176 static int ieee80211_hwmp_pathtimeout = -1; 177 SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, pathlifetime, CTLTYPE_INT | CTLFLAG_RW, 178 &ieee80211_hwmp_pathtimeout, 0, ieee80211_sysctl_msecs_ticks, "I", 179 "path entry lifetime (ms)"); 180 static int ieee80211_hwmp_roottimeout = -1; 181 SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, roottimeout, CTLTYPE_INT | CTLFLAG_RW, 182 &ieee80211_hwmp_roottimeout, 0, ieee80211_sysctl_msecs_ticks, "I", 183 "root PREQ timeout (ms)"); 184 static int ieee80211_hwmp_rootint = -1; 185 SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, rootint, CTLTYPE_INT | CTLFLAG_RW, 186 &ieee80211_hwmp_rootint, 0, ieee80211_sysctl_msecs_ticks, "I", 187 "root interval (ms)"); 188 static int ieee80211_hwmp_rannint = -1; 189 SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, rannint, CTLTYPE_INT | CTLFLAG_RW, 190 &ieee80211_hwmp_rannint, 0, ieee80211_sysctl_msecs_ticks, "I", 191 "root announcement interval (ms)"); 192 193 #define IEEE80211_HWMP_DEFAULT_MAXHOPS 31 194 195 static ieee80211_recv_action_func hwmp_recv_action_meshpath; 196 197 static struct ieee80211_mesh_proto_path mesh_proto_hwmp = { 198 .mpp_descr = "HWMP", 199 .mpp_ie = IEEE80211_MESHCONF_PATH_HWMP, 200 .mpp_discover = hwmp_discover, 201 .mpp_peerdown = hwmp_peerdown, 202 .mpp_vattach = hwmp_vattach, 203 .mpp_vdetach = hwmp_vdetach, 204 .mpp_newstate = hwmp_newstate, 205 .mpp_privlen = sizeof(struct ieee80211_hwmp_route), 206 }; 207 SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, inact, CTLTYPE_INT | CTLFLAG_RW, 208 &mesh_proto_hwmp.mpp_inact, 0, ieee80211_sysctl_msecs_ticks, "I", 209 "mesh route inactivity timeout (ms)"); 210 211 212 static void 213 ieee80211_hwmp_init(void) 214 { 215 ieee80211_hwmp_pathtimeout = msecs_to_ticks(5*1000); 216 ieee80211_hwmp_roottimeout = msecs_to_ticks(5*1000); 217 ieee80211_hwmp_rootint = msecs_to_ticks(2*1000); 218 ieee80211_hwmp_rannint = msecs_to_ticks(1*1000); 219 220 /* 221 * Register action frame handler. 222 */ 223 ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH, 224 IEEE80211_ACTION_MESH_HWMP, hwmp_recv_action_meshpath); 225 226 /* NB: default is 5 secs per spec */ 227 mesh_proto_hwmp.mpp_inact = msecs_to_ticks(5*1000); 228 229 /* 230 * Register HWMP. 231 */ 232 ieee80211_mesh_register_proto_path(&mesh_proto_hwmp); 233 } 234 SYSINIT(wlan_hwmp, SI_SUB_DRIVERS, SI_ORDER_SECOND, ieee80211_hwmp_init, NULL); 235 236 void 237 hwmp_vattach(struct ieee80211vap *vap) 238 { 239 struct ieee80211_hwmp_state *hs; 240 241 KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, 242 ("not a mesh vap, opmode %d", vap->iv_opmode)); 243 244 hs = malloc(sizeof(struct ieee80211_hwmp_state), M_80211_VAP, 245 M_NOWAIT | M_ZERO); 246 if (hs == NULL) { 247 printf("%s: couldn't alloc HWMP state\n", __func__); 248 return; 249 } 250 hs->hs_maxhops = IEEE80211_HWMP_DEFAULT_MAXHOPS; 251 callout_init(&hs->hs_roottimer, CALLOUT_MPSAFE); 252 vap->iv_hwmp = hs; 253 } 254 255 void 256 hwmp_vdetach(struct ieee80211vap *vap) 257 { 258 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 259 260 callout_drain(&hs->hs_roottimer); 261 free(vap->iv_hwmp, M_80211_VAP); 262 vap->iv_hwmp = NULL; 263 } 264 265 int 266 hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg) 267 { 268 enum ieee80211_state nstate = vap->iv_state; 269 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 270 271 IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n", 272 __func__, ieee80211_state_name[ostate], 273 ieee80211_state_name[nstate], arg); 274 275 if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN) 276 callout_drain(&hs->hs_roottimer); 277 if (nstate == IEEE80211_S_RUN) 278 hwmp_rootmode_setup(vap); 279 return 0; 280 } 281 282 /* 283 * Verify the length of an HWMP PREQ and return the number 284 * of destinations >= 1, if verification fails -1 is returned. 285 */ 286 static int 287 verify_mesh_preq_len(struct ieee80211vap *vap, 288 const struct ieee80211_frame *wh, const uint8_t *iefrm) 289 { 290 int alloc_sz = -1; 291 int ndest = -1; 292 if (iefrm[2] & IEEE80211_MESHPREQ_FLAGS_AE) { 293 /* Originator External Address present */ 294 alloc_sz = IEEE80211_MESHPREQ_BASE_SZ_AE; 295 ndest = iefrm[IEEE80211_MESHPREQ_TCNT_OFFSET_AE]; 296 } else { 297 /* w/o Originator External Address */ 298 alloc_sz = IEEE80211_MESHPREQ_BASE_SZ; 299 ndest = iefrm[IEEE80211_MESHPREQ_TCNT_OFFSET]; 300 } 301 alloc_sz += ndest * IEEE80211_MESHPREQ_TRGT_SZ; 302 303 if(iefrm[1] != (alloc_sz)) { 304 IEEE80211_DISCARD(vap, 305 IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, 306 wh, NULL, "PREQ (AE=%s) with wrong len", 307 iefrm[2] & IEEE80211_MESHPREQ_FLAGS_AE ? "1" : "0"); 308 return (-1); 309 } 310 return ndest; 311 } 312 313 /* 314 * Verify the length of an HWMP PREP and returns 1 on success, 315 * otherwise -1. 316 */ 317 static int 318 verify_mesh_prep_len(struct ieee80211vap *vap, 319 const struct ieee80211_frame *wh, const uint8_t *iefrm) 320 { 321 int alloc_sz = -1; 322 if (iefrm[2] & IEEE80211_MESHPREP_FLAGS_AE) { 323 if (iefrm[1] == IEEE80211_MESHPREP_BASE_SZ_AE) 324 alloc_sz = IEEE80211_MESHPREP_BASE_SZ_AE; 325 } else if (iefrm[1] == IEEE80211_MESHPREP_BASE_SZ) 326 alloc_sz = IEEE80211_MESHPREP_BASE_SZ; 327 if(alloc_sz < 0) { 328 IEEE80211_DISCARD(vap, 329 IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, 330 wh, NULL, "PREP (AE=%s) with wrong len", 331 iefrm[2] & IEEE80211_MESHPREP_FLAGS_AE ? "1" : "0"); 332 return (-1); 333 } 334 return (1); 335 } 336 337 /* 338 * Verify the length of an HWMP PERR and return the number 339 * of destinations >= 1, if verification fails -1 is returned. 340 */ 341 static int 342 verify_mesh_perr_len(struct ieee80211vap *vap, 343 const struct ieee80211_frame *wh, const uint8_t *iefrm) 344 { 345 int alloc_sz = -1; 346 const uint8_t *iefrm_t = iefrm; 347 uint8_t ndest = iefrm_t[IEEE80211_MESHPERR_NDEST_OFFSET]; 348 int i; 349 350 if(ndest > IEEE80211_MESHPERR_MAXDEST) { 351 IEEE80211_DISCARD(vap, 352 IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, 353 wh, NULL, "PERR with wrong number of destionat (>19), %u", 354 ndest); 355 return (-1); 356 } 357 358 iefrm_t += IEEE80211_MESHPERR_NDEST_OFFSET + 1; /* flag is next field */ 359 /* We need to check each destionation flag to know size */ 360 for(i = 0; i<ndest; i++) { 361 if ((*iefrm_t) & IEEE80211_MESHPERR_FLAGS_AE) 362 iefrm_t += IEEE80211_MESHPERR_DEST_SZ_AE; 363 else 364 iefrm_t += IEEE80211_MESHPERR_DEST_SZ; 365 } 366 367 alloc_sz = (iefrm_t - iefrm) - 2; /* action + code */ 368 if(alloc_sz != iefrm[1]) { 369 IEEE80211_DISCARD(vap, 370 IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, 371 wh, NULL, "%s", "PERR with wrong len"); 372 return (-1); 373 } 374 return ndest; 375 } 376 377 static int 378 hwmp_recv_action_meshpath(struct ieee80211_node *ni, 379 const struct ieee80211_frame *wh, 380 const uint8_t *frm, const uint8_t *efrm) 381 { 382 struct ieee80211vap *vap = ni->ni_vap; 383 struct ieee80211_meshpreq_ie *preq; 384 struct ieee80211_meshprep_ie *prep; 385 struct ieee80211_meshperr_ie *perr; 386 struct ieee80211_meshrann_ie rann; 387 const uint8_t *iefrm = frm + 2; /* action + code */ 388 const uint8_t *iefrm_t = iefrm; /* temporary pointer */ 389 int ndest = -1; 390 int found = 0; 391 392 while (efrm - iefrm > 1) { 393 IEEE80211_VERIFY_LENGTH(efrm - iefrm, iefrm[1] + 2, return 0); 394 switch (*iefrm) { 395 case IEEE80211_ELEMID_MESHPREQ: 396 { 397 int i = 0; 398 399 iefrm_t = iefrm; 400 ndest = verify_mesh_preq_len(vap, wh, iefrm_t); 401 if (ndest < 0) { 402 vap->iv_stats.is_rx_mgtdiscard++; 403 break; 404 } 405 preq = malloc(sizeof(*preq) + 406 (ndest - 1) * sizeof(*preq->preq_targets), 407 M_80211_MESH_PREQ, M_NOWAIT | M_ZERO); 408 KASSERT(preq != NULL, ("preq == NULL")); 409 410 preq->preq_ie = *iefrm_t++; 411 preq->preq_len = *iefrm_t++; 412 preq->preq_flags = *iefrm_t++; 413 preq->preq_hopcount = *iefrm_t++; 414 preq->preq_ttl = *iefrm_t++; 415 preq->preq_id = LE_READ_4(iefrm_t); iefrm_t += 4; 416 IEEE80211_ADDR_COPY(preq->preq_origaddr, iefrm_t); 417 iefrm_t += 6; 418 preq->preq_origseq = LE_READ_4(iefrm_t); iefrm_t += 4; 419 /* NB: may have Originator Proxied Address */ 420 if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE) { 421 IEEE80211_ADDR_COPY( 422 preq->preq_orig_ext_addr, iefrm_t); 423 iefrm_t += 6; 424 } 425 preq->preq_lifetime = LE_READ_4(iefrm_t); iefrm_t += 4; 426 preq->preq_metric = LE_READ_4(iefrm_t); iefrm_t += 4; 427 preq->preq_tcount = *iefrm_t++; 428 429 for (i = 0; i < preq->preq_tcount; i++) { 430 preq->preq_targets[i].target_flags = *iefrm_t++; 431 IEEE80211_ADDR_COPY( 432 preq->preq_targets[i].target_addr, iefrm_t); 433 iefrm_t += 6; 434 preq->preq_targets[i].target_seq = 435 LE_READ_4(iefrm_t); 436 iefrm_t += 4; 437 } 438 439 hwmp_recv_preq(vap, ni, wh, preq); 440 free(preq, M_80211_MESH_PREQ); 441 found++; 442 break; 443 } 444 case IEEE80211_ELEMID_MESHPREP: 445 { 446 iefrm_t = iefrm; 447 ndest = verify_mesh_prep_len(vap, wh, iefrm_t); 448 if (ndest < 0) { 449 vap->iv_stats.is_rx_mgtdiscard++; 450 break; 451 } 452 prep = malloc(sizeof(*prep), 453 M_80211_MESH_PREP, M_NOWAIT | M_ZERO); 454 KASSERT(prep != NULL, ("prep == NULL")); 455 456 prep->prep_ie = *iefrm_t++; 457 prep->prep_len = *iefrm_t++; 458 prep->prep_flags = *iefrm_t++; 459 prep->prep_hopcount = *iefrm_t++; 460 prep->prep_ttl = *iefrm_t++; 461 IEEE80211_ADDR_COPY(prep->prep_targetaddr, iefrm_t); 462 iefrm_t += 6; 463 prep->prep_targetseq = LE_READ_4(iefrm_t); iefrm_t += 4; 464 /* NB: May have Target Proxied Address */ 465 if (prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE) { 466 IEEE80211_ADDR_COPY( 467 prep->prep_target_ext_addr, iefrm_t); 468 iefrm_t += 6; 469 } 470 prep->prep_lifetime = LE_READ_4(iefrm_t); iefrm_t += 4; 471 prep->prep_metric = LE_READ_4(iefrm_t); iefrm_t += 4; 472 IEEE80211_ADDR_COPY(prep->prep_origaddr, iefrm_t); 473 iefrm_t += 6; 474 prep->prep_origseq = LE_READ_4(iefrm_t); iefrm_t += 4; 475 476 hwmp_recv_prep(vap, ni, wh, prep); 477 free(prep, M_80211_MESH_PREP); 478 found++; 479 break; 480 } 481 case IEEE80211_ELEMID_MESHPERR: 482 { 483 int i = 0; 484 485 iefrm_t = iefrm; 486 ndest = verify_mesh_perr_len(vap, wh, iefrm_t); 487 if (ndest < 0) { 488 vap->iv_stats.is_rx_mgtdiscard++; 489 break; 490 } 491 perr = malloc(sizeof(*perr) + 492 (ndest - 1) * sizeof(*perr->perr_dests), 493 M_80211_MESH_PERR, M_NOWAIT | M_ZERO); 494 KASSERT(perr != NULL, ("perr == NULL")); 495 496 perr->perr_ie = *iefrm_t++; 497 perr->perr_len = *iefrm_t++; 498 perr->perr_ttl = *iefrm_t++; 499 perr->perr_ndests = *iefrm_t++; 500 501 for (i = 0; i<perr->perr_ndests; i++) { 502 perr->perr_dests[i].dest_flags = *iefrm_t++; 503 IEEE80211_ADDR_COPY( 504 perr->perr_dests[i].dest_addr, iefrm_t); 505 iefrm_t += 6; 506 perr->perr_dests[i].dest_seq = LE_READ_4(iefrm_t); 507 iefrm_t += 4; 508 /* NB: May have Target Proxied Address */ 509 if (perr->perr_dests[i].dest_flags & 510 IEEE80211_MESHPERR_FLAGS_AE) { 511 IEEE80211_ADDR_COPY( 512 perr->perr_dests[i].dest_ext_addr, 513 iefrm_t); 514 iefrm_t += 6; 515 } 516 perr->perr_dests[i].dest_rcode = 517 LE_READ_2(iefrm_t); 518 iefrm_t += 2; 519 } 520 521 hwmp_recv_perr(vap, ni, wh, perr); 522 free(perr, M_80211_MESH_PERR); 523 found++; 524 break; 525 } 526 case IEEE80211_ELEMID_MESHRANN: 527 { 528 const struct ieee80211_meshrann_ie *mrann = 529 (const struct ieee80211_meshrann_ie *) iefrm; 530 if (mrann->rann_len != 531 sizeof(struct ieee80211_meshrann_ie) - 2) { 532 IEEE80211_DISCARD(vap, 533 IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, 534 wh, NULL, "%s", "RAN with wrong len"); 535 vap->iv_stats.is_rx_mgtdiscard++; 536 return 1; 537 } 538 memcpy(&rann, mrann, sizeof(rann)); 539 rann.rann_seq = LE_READ_4(&mrann->rann_seq); 540 rann.rann_metric = LE_READ_4(&mrann->rann_metric); 541 hwmp_recv_rann(vap, ni, wh, &rann); 542 found++; 543 break; 544 } 545 } 546 iefrm += iefrm[1] + 2; 547 } 548 if (!found) { 549 IEEE80211_DISCARD(vap, 550 IEEE80211_MSG_ACTION | IEEE80211_MSG_HWMP, 551 wh, NULL, "%s", "PATH SEL action without IE"); 552 vap->iv_stats.is_rx_mgtdiscard++; 553 } 554 return 0; 555 } 556 557 static int 558 hwmp_send_action(struct ieee80211_node *ni, 559 const uint8_t sa[IEEE80211_ADDR_LEN], 560 const uint8_t da[IEEE80211_ADDR_LEN], 561 uint8_t *ie, size_t len) 562 { 563 struct ieee80211vap *vap = ni->ni_vap; 564 struct ieee80211com *ic = ni->ni_ic; 565 struct ieee80211_bpf_params params; 566 struct mbuf *m; 567 uint8_t *frm; 568 569 if (vap->iv_state == IEEE80211_S_CAC) { 570 IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni, 571 "block %s frame in CAC state", "HWMP action"); 572 vap->iv_stats.is_tx_badstate++; 573 return EIO; /* XXX */ 574 } 575 576 KASSERT(ni != NULL, ("null node")); 577 /* 578 * Hold a reference on the node so it doesn't go away until after 579 * the xmit is complete all the way in the driver. On error we 580 * will remove our reference. 581 */ 582 #ifdef IEEE80211_DEBUG_REFCNT 583 IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 584 "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", 585 __func__, __LINE__, 586 ni, ether_sprintf(ni->ni_macaddr), 587 ieee80211_node_refcnt(ni)+1); 588 #endif 589 ieee80211_ref_node(ni); 590 591 m = ieee80211_getmgtframe(&frm, 592 ic->ic_headroom + sizeof(struct ieee80211_frame), 593 sizeof(struct ieee80211_action) + len 594 ); 595 if (m == NULL) { 596 ieee80211_free_node(ni); 597 vap->iv_stats.is_tx_nobuf++; 598 return ENOMEM; 599 } 600 *frm++ = IEEE80211_ACTION_CAT_MESH; 601 *frm++ = IEEE80211_ACTION_MESH_HWMP; 602 switch (*ie) { 603 case IEEE80211_ELEMID_MESHPREQ: 604 frm = hwmp_add_meshpreq(frm, 605 (struct ieee80211_meshpreq_ie *)ie); 606 break; 607 case IEEE80211_ELEMID_MESHPREP: 608 frm = hwmp_add_meshprep(frm, 609 (struct ieee80211_meshprep_ie *)ie); 610 break; 611 case IEEE80211_ELEMID_MESHPERR: 612 frm = hwmp_add_meshperr(frm, 613 (struct ieee80211_meshperr_ie *)ie); 614 break; 615 case IEEE80211_ELEMID_MESHRANN: 616 frm = hwmp_add_meshrann(frm, 617 (struct ieee80211_meshrann_ie *)ie); 618 break; 619 } 620 621 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); 622 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); 623 if (m == NULL) { 624 ieee80211_free_node(ni); 625 vap->iv_stats.is_tx_nobuf++; 626 return ENOMEM; 627 } 628 ieee80211_send_setup(ni, m, 629 IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION, 630 IEEE80211_NONQOS_TID, sa, da, sa); 631 632 m->m_flags |= M_ENCAP; /* mark encapsulated */ 633 IEEE80211_NODE_STAT(ni, tx_mgmt); 634 635 memset(¶ms, 0, sizeof(params)); 636 params.ibp_pri = WME_AC_VO; 637 params.ibp_rate0 = ni->ni_txparms->mgmtrate; 638 if (IEEE80211_IS_MULTICAST(da)) 639 params.ibp_try0 = 1; 640 else 641 params.ibp_try0 = ni->ni_txparms->maxretry; 642 params.ibp_power = ni->ni_txpower; 643 return ic->ic_raw_xmit(ni, m, ¶ms); 644 } 645 646 #define ADDSHORT(frm, v) do { \ 647 frm[0] = (v) & 0xff; \ 648 frm[1] = (v) >> 8; \ 649 frm += 2; \ 650 } while (0) 651 #define ADDWORD(frm, v) do { \ 652 LE_WRITE_4(frm, v); \ 653 frm += 4; \ 654 } while (0) 655 /* 656 * Add a Mesh Path Request IE to a frame. 657 */ 658 #define PREQ_TFLAGS(n) preq->preq_targets[n].target_flags 659 #define PREQ_TADDR(n) preq->preq_targets[n].target_addr 660 #define PREQ_TSEQ(n) preq->preq_targets[n].target_seq 661 static uint8_t * 662 hwmp_add_meshpreq(uint8_t *frm, const struct ieee80211_meshpreq_ie *preq) 663 { 664 int i; 665 666 *frm++ = IEEE80211_ELEMID_MESHPREQ; 667 *frm++ = preq->preq_len; /* len already calculated */ 668 *frm++ = preq->preq_flags; 669 *frm++ = preq->preq_hopcount; 670 *frm++ = preq->preq_ttl; 671 ADDWORD(frm, preq->preq_id); 672 IEEE80211_ADDR_COPY(frm, preq->preq_origaddr); frm += 6; 673 ADDWORD(frm, preq->preq_origseq); 674 if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE) { 675 IEEE80211_ADDR_COPY(frm, preq->preq_orig_ext_addr); 676 frm += 6; 677 } 678 ADDWORD(frm, preq->preq_lifetime); 679 ADDWORD(frm, preq->preq_metric); 680 *frm++ = preq->preq_tcount; 681 for (i = 0; i < preq->preq_tcount; i++) { 682 *frm++ = PREQ_TFLAGS(i); 683 IEEE80211_ADDR_COPY(frm, PREQ_TADDR(i)); 684 frm += 6; 685 ADDWORD(frm, PREQ_TSEQ(i)); 686 } 687 return frm; 688 } 689 #undef PREQ_TFLAGS 690 #undef PREQ_TADDR 691 #undef PREQ_TSEQ 692 693 /* 694 * Add a Mesh Path Reply IE to a frame. 695 */ 696 static uint8_t * 697 hwmp_add_meshprep(uint8_t *frm, const struct ieee80211_meshprep_ie *prep) 698 { 699 *frm++ = IEEE80211_ELEMID_MESHPREP; 700 *frm++ = prep->prep_len; /* len already calculated */ 701 *frm++ = prep->prep_flags; 702 *frm++ = prep->prep_hopcount; 703 *frm++ = prep->prep_ttl; 704 IEEE80211_ADDR_COPY(frm, prep->prep_targetaddr); frm += 6; 705 ADDWORD(frm, prep->prep_targetseq); 706 if (prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE) { 707 IEEE80211_ADDR_COPY(frm, prep->prep_target_ext_addr); 708 frm += 6; 709 } 710 ADDWORD(frm, prep->prep_lifetime); 711 ADDWORD(frm, prep->prep_metric); 712 IEEE80211_ADDR_COPY(frm, prep->prep_origaddr); frm += 6; 713 ADDWORD(frm, prep->prep_origseq); 714 return frm; 715 } 716 717 /* 718 * Add a Mesh Path Error IE to a frame. 719 */ 720 #define PERR_DFLAGS(n) perr->perr_dests[n].dest_flags 721 #define PERR_DADDR(n) perr->perr_dests[n].dest_addr 722 #define PERR_DSEQ(n) perr->perr_dests[n].dest_seq 723 #define PERR_EXTADDR(n) perr->perr_dests[n].dest_ext_addr 724 #define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode 725 static uint8_t * 726 hwmp_add_meshperr(uint8_t *frm, const struct ieee80211_meshperr_ie *perr) 727 { 728 int i; 729 730 *frm++ = IEEE80211_ELEMID_MESHPERR; 731 *frm++ = perr->perr_len; /* len already calculated */ 732 *frm++ = perr->perr_ttl; 733 *frm++ = perr->perr_ndests; 734 for (i = 0; i < perr->perr_ndests; i++) { 735 *frm++ = PERR_DFLAGS(i); 736 IEEE80211_ADDR_COPY(frm, PERR_DADDR(i)); 737 frm += 6; 738 ADDWORD(frm, PERR_DSEQ(i)); 739 if (PERR_DFLAGS(i) & IEEE80211_MESHPERR_FLAGS_AE) { 740 IEEE80211_ADDR_COPY(frm, PERR_EXTADDR(i)); 741 frm += 6; 742 } 743 ADDSHORT(frm, PERR_DRCODE(i)); 744 } 745 return frm; 746 } 747 #undef PERR_DFLAGS 748 #undef PERR_DADDR 749 #undef PERR_DSEQ 750 #undef PERR_EXTADDR 751 #undef PERR_DRCODE 752 753 /* 754 * Add a Root Annoucement IE to a frame. 755 */ 756 static uint8_t * 757 hwmp_add_meshrann(uint8_t *frm, const struct ieee80211_meshrann_ie *rann) 758 { 759 *frm++ = IEEE80211_ELEMID_MESHRANN; 760 *frm++ = rann->rann_len; 761 *frm++ = rann->rann_flags; 762 *frm++ = rann->rann_hopcount; 763 *frm++ = rann->rann_ttl; 764 IEEE80211_ADDR_COPY(frm, rann->rann_addr); frm += 6; 765 ADDWORD(frm, rann->rann_seq); 766 ADDWORD(frm, rann->rann_interval); 767 ADDWORD(frm, rann->rann_metric); 768 return frm; 769 } 770 771 static void 772 hwmp_rootmode_setup(struct ieee80211vap *vap) 773 { 774 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 775 776 switch (hs->hs_rootmode) { 777 case IEEE80211_HWMP_ROOTMODE_DISABLED: 778 callout_drain(&hs->hs_roottimer); 779 break; 780 case IEEE80211_HWMP_ROOTMODE_NORMAL: 781 case IEEE80211_HWMP_ROOTMODE_PROACTIVE: 782 callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rootint, 783 hwmp_rootmode_cb, vap); 784 break; 785 case IEEE80211_HWMP_ROOTMODE_RANN: 786 callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rannint, 787 hwmp_rootmode_rann_cb, vap); 788 break; 789 } 790 } 791 792 /* 793 * Send a broadcast Path Request to find all nodes on the mesh. We are 794 * called when the vap is configured as a HWMP root node. 795 */ 796 #define PREQ_TFLAGS(n) preq.preq_targets[n].target_flags 797 #define PREQ_TADDR(n) preq.preq_targets[n].target_addr 798 #define PREQ_TSEQ(n) preq.preq_targets[n].target_seq 799 static void 800 hwmp_rootmode_cb(void *arg) 801 { 802 struct ieee80211vap *vap = (struct ieee80211vap *)arg; 803 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 804 struct ieee80211_mesh_state *ms = vap->iv_mesh; 805 struct ieee80211_meshpreq_ie preq; 806 807 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss, 808 "%s", "send broadcast PREQ"); 809 810 preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM; 811 if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL) 812 preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PR; 813 if (hs->hs_rootmode == IEEE80211_HWMP_ROOTMODE_PROACTIVE) 814 preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PP; 815 preq.preq_hopcount = 0; 816 preq.preq_ttl = ms->ms_ttl; 817 preq.preq_id = ++hs->hs_preqid; 818 IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr); 819 preq.preq_origseq = ++hs->hs_seq; 820 preq.preq_lifetime = ticks_to_msecs(ieee80211_hwmp_roottimeout); 821 preq.preq_metric = IEEE80211_MESHLMETRIC_INITIALVAL; 822 preq.preq_tcount = 1; 823 IEEE80211_ADDR_COPY(PREQ_TADDR(0), broadcastaddr); 824 PREQ_TFLAGS(0) = IEEE80211_MESHPREQ_TFLAGS_TO | 825 IEEE80211_MESHPREQ_TFLAGS_RF; 826 PREQ_TSEQ(0) = 0; 827 vap->iv_stats.is_hwmp_rootreqs++; 828 hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq); 829 hwmp_rootmode_setup(vap); 830 } 831 #undef PREQ_TFLAGS 832 #undef PREQ_TADDR 833 #undef PREQ_TSEQ 834 835 /* 836 * Send a Root Annoucement (RANN) to find all the nodes on the mesh. We are 837 * called when the vap is configured as a HWMP RANN root node. 838 */ 839 static void 840 hwmp_rootmode_rann_cb(void *arg) 841 { 842 struct ieee80211vap *vap = (struct ieee80211vap *)arg; 843 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 844 struct ieee80211_mesh_state *ms = vap->iv_mesh; 845 struct ieee80211_meshrann_ie rann; 846 847 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss, 848 "%s", "send broadcast RANN"); 849 850 rann.rann_flags = 0; 851 if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL) 852 rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR; 853 rann.rann_hopcount = 0; 854 rann.rann_ttl = ms->ms_ttl; 855 IEEE80211_ADDR_COPY(rann.rann_addr, vap->iv_myaddr); 856 rann.rann_seq = ++hs->hs_seq; 857 rann.rann_metric = IEEE80211_MESHLMETRIC_INITIALVAL; 858 859 vap->iv_stats.is_hwmp_rootrann++; 860 hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &rann); 861 hwmp_rootmode_setup(vap); 862 } 863 864 #define PREQ_TFLAGS(n) preq->preq_targets[n].target_flags 865 #define PREQ_TADDR(n) preq->preq_targets[n].target_addr 866 #define PREQ_TSEQ(n) preq->preq_targets[n].target_seq 867 static void 868 hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, 869 const struct ieee80211_frame *wh, const struct ieee80211_meshpreq_ie *preq) 870 { 871 struct ieee80211_mesh_state *ms = vap->iv_mesh; 872 struct ieee80211_mesh_route *rt = NULL; 873 struct ieee80211_mesh_route *rtorig = NULL; 874 struct ieee80211_mesh_route *rttarg = NULL; 875 struct ieee80211_hwmp_route *hrorig = NULL; 876 struct ieee80211_hwmp_route *hrtarg = NULL; 877 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 878 struct ieee80211_meshprep_ie prep; 879 880 if (ni == vap->iv_bss || 881 ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) 882 return; 883 /* 884 * Ignore PREQs from us. Could happen because someone forward it 885 * back to us. 886 */ 887 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, preq->preq_origaddr)) 888 return; 889 890 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 891 "received PREQ, source %6D", preq->preq_origaddr, ":"); 892 893 /* 894 * Acceptance criteria: if the PREQ is not for us or not broadcast 895 * AND forwarding is disabled, discard this PREQ. 896 * XXX: need to check PROXY 897 */ 898 if ((!IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) || 899 !IEEE80211_IS_MULTICAST(PREQ_TADDR(0))) && 900 !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) { 901 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP, 902 preq->preq_origaddr, NULL, "%s", "not accepting PREQ"); 903 return; 904 } 905 /* 906 * Acceptance criteria: if unicast addressed 907 * AND no valid forwarding for Target of PREQ, discard this PREQ. 908 */ 909 rttarg = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0)); 910 if(rttarg != NULL) 911 hrtarg = IEEE80211_MESH_ROUTE_PRIV(rttarg, 912 struct ieee80211_hwmp_route); 913 /* Address mode: ucast */ 914 if((preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AM) == 0 && 915 rttarg == NULL && 916 !IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) { 917 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP, 918 preq->preq_origaddr, NULL, 919 "unicast addressed PREQ of unknown target %6D", 920 PREQ_TADDR(0), ":"); 921 return; 922 } 923 924 /* PREQ ACCEPTED */ 925 926 rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr); 927 if (rtorig == NULL) { 928 rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr); 929 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 930 "adding originator %6D", preq->preq_origaddr, ":"); 931 } 932 if (rtorig == NULL) { 933 /* XXX stat */ 934 return; 935 } 936 hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route); 937 938 /* Data creation and update of forwarding information 939 * according to Table 11C-8 for originator mesh STA. 940 */ 941 if(HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) || 942 (HWMP_SEQ_EQ(preq->preq_origseq, hrorig->hr_seq) && 943 preq->preq_metric < rtorig->rt_metric)) { 944 hrorig->hr_seq = preq->preq_origseq; 945 IEEE80211_ADDR_COPY(rtorig->rt_nexthop, wh->i_addr2); 946 rtorig->rt_metric = preq->preq_metric + 947 ms->ms_pmetric->mpm_metric(ni); 948 rtorig->rt_nhops = preq->preq_hopcount + 1; 949 rtorig->rt_lifetime = MESH_ROUTE_LIFETIME_MAX( 950 preq->preq_lifetime, rtorig->rt_lifetime); 951 /* path to orig is valid now */ 952 rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; 953 }else if(hrtarg != NULL && 954 HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) && 955 (rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { 956 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 957 "discard PREQ from %6D, old seq no %u <= %u", 958 preq->preq_origaddr, ":", 959 preq->preq_origseq, hrorig->hr_seq); 960 return; 961 } 962 963 /* 964 * Forwarding information for transmitter mesh STA 965 * [OPTIONAL: if metric improved] 966 */ 967 968 /* 969 * Check if the PREQ is addressed to us. 970 */ 971 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0))) { 972 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 973 "reply to %6D", preq->preq_origaddr, ":"); 974 /* 975 * Build and send a PREP frame. 976 */ 977 prep.prep_flags = 0; 978 prep.prep_hopcount = 0; 979 prep.prep_ttl = ms->ms_ttl; 980 IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr); 981 prep.prep_targetseq = ++hs->hs_seq; 982 prep.prep_lifetime = preq->preq_lifetime; 983 prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL; 984 IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr); 985 prep.prep_origseq = preq->preq_origseq; 986 hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep); 987 /* 988 * Build the reverse path, if we don't have it already. 989 */ 990 rt = ieee80211_mesh_rt_find(vap, preq->preq_origaddr); 991 if (rt == NULL) 992 hwmp_discover(vap, preq->preq_origaddr, NULL); 993 else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) 994 hwmp_discover(vap, rt->rt_dest, NULL); 995 return; 996 } 997 /* 998 * Proactive PREQ: reply with a proactive PREP to the 999 * root STA if requested. 1000 */ 1001 if (IEEE80211_ADDR_EQ(PREQ_TADDR(0), broadcastaddr) && 1002 (PREQ_TFLAGS(0) & 1003 ((IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF) == 1004 (IEEE80211_MESHPREQ_TFLAGS_TO|IEEE80211_MESHPREQ_TFLAGS_RF)))) { 1005 uint8_t rootmac[IEEE80211_ADDR_LEN]; 1006 1007 IEEE80211_ADDR_COPY(rootmac, preq->preq_origaddr); 1008 rt = ieee80211_mesh_rt_find(vap, rootmac); 1009 if (rt == NULL) { 1010 rt = ieee80211_mesh_rt_add(vap, rootmac); 1011 if (rt == NULL) { 1012 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1013 "unable to add root mesh path to %6D", 1014 rootmac, ":"); 1015 vap->iv_stats.is_mesh_rtaddfailed++; 1016 return; 1017 } 1018 } 1019 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1020 "root mesh station @ %6D", rootmac, ":"); 1021 1022 /* 1023 * Reply with a PREP if we don't have a path to the root 1024 * or if the root sent us a proactive PREQ. 1025 */ 1026 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 || 1027 (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_PP)) { 1028 prep.prep_flags = 0; 1029 prep.prep_hopcount = 0; 1030 prep.prep_ttl = ms->ms_ttl; 1031 IEEE80211_ADDR_COPY(prep.prep_origaddr, rootmac); 1032 prep.prep_origseq = preq->preq_origseq; 1033 prep.prep_lifetime = preq->preq_lifetime; 1034 prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL; 1035 IEEE80211_ADDR_COPY(prep.prep_targetaddr, 1036 vap->iv_myaddr); 1037 prep.prep_targetseq = ++hs->hs_seq; 1038 hwmp_send_prep(vap->iv_bss, vap->iv_myaddr, 1039 broadcastaddr, &prep); 1040 } 1041 hwmp_discover(vap, rootmac, NULL); 1042 return; 1043 } 1044 rt = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0)); 1045 1046 /* 1047 * Forwarding and Intermediate reply for PREQs with 1 target. 1048 */ 1049 if (preq->preq_tcount == 1) { 1050 struct ieee80211_meshpreq_ie ppreq; /* propagated PREQ */ 1051 1052 memcpy(&ppreq, preq, sizeof(ppreq)); 1053 /* 1054 * We have a valid route to this node. 1055 */ 1056 if (rt != NULL && 1057 (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) { 1058 if (preq->preq_ttl > 1 && 1059 preq->preq_hopcount < hs->hs_maxhops) { 1060 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1061 "forward PREQ from %6D", 1062 preq->preq_origaddr, ":"); 1063 /* 1064 * Propagate the original PREQ. 1065 * PREQ is unicast now to rt->rt_nexthop 1066 */ 1067 ppreq.preq_flags &= 1068 ~IEEE80211_MESHPREQ_FLAGS_AM; 1069 ppreq.preq_hopcount += 1; 1070 ppreq.preq_ttl -= 1; 1071 ppreq.preq_metric += 1072 ms->ms_pmetric->mpm_metric(ni); 1073 /* 1074 * Set TO and unset RF bits because we are 1075 * going to send a PREP next. 1076 */ 1077 ppreq.preq_targets[0].target_flags |= 1078 IEEE80211_MESHPREQ_TFLAGS_TO; 1079 ppreq.preq_targets[0].target_flags &= 1080 ~IEEE80211_MESHPREQ_TFLAGS_RF; 1081 hwmp_send_preq(ni, vap->iv_myaddr, 1082 rt->rt_nexthop, &ppreq); 1083 } 1084 /* 1085 * Check if we can send an intermediate Path Reply, 1086 * i.e., Target Only bit is not set. 1087 */ 1088 if (!(PREQ_TFLAGS(0) & IEEE80211_MESHPREQ_TFLAGS_TO)) { 1089 struct ieee80211_meshprep_ie prep; 1090 1091 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1092 "intermediate reply for PREQ from %6D", 1093 preq->preq_origaddr, ":"); 1094 prep.prep_flags = 0; 1095 prep.prep_hopcount = rt->rt_nhops + 1; 1096 prep.prep_ttl = ms->ms_ttl; 1097 IEEE80211_ADDR_COPY(&prep.prep_targetaddr, 1098 PREQ_TADDR(0)); 1099 prep.prep_targetseq = hrorig->hr_seq; 1100 prep.prep_lifetime = preq->preq_lifetime; 1101 prep.prep_metric = rt->rt_metric + 1102 ms->ms_pmetric->mpm_metric(ni); 1103 IEEE80211_ADDR_COPY(&prep.prep_origaddr, 1104 preq->preq_origaddr); 1105 prep.prep_origseq = hrorig->hr_seq; 1106 hwmp_send_prep(ni, vap->iv_myaddr, 1107 broadcastaddr, &prep); 1108 } 1109 /* 1110 * We have no information about this path, 1111 * propagate the PREQ. 1112 */ 1113 } else if (preq->preq_ttl > 1 && 1114 preq->preq_hopcount < hs->hs_maxhops) { 1115 if (rt == NULL) { 1116 rt = ieee80211_mesh_rt_add(vap, PREQ_TADDR(0)); 1117 if (rt == NULL) { 1118 IEEE80211_NOTE(vap, 1119 IEEE80211_MSG_HWMP, ni, 1120 "unable to add PREQ path to %6D", 1121 PREQ_TADDR(0), ":"); 1122 vap->iv_stats.is_mesh_rtaddfailed++; 1123 return; 1124 } 1125 } 1126 rt->rt_metric = preq->preq_metric; 1127 rt->rt_lifetime = preq->preq_lifetime; 1128 hrorig = IEEE80211_MESH_ROUTE_PRIV(rt, 1129 struct ieee80211_hwmp_route); 1130 hrorig->hr_seq = preq->preq_origseq; 1131 hrorig->hr_preqid = preq->preq_id; 1132 1133 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1134 "forward PREQ from %6D", 1135 preq->preq_origaddr, ":"); 1136 ppreq.preq_hopcount += 1; 1137 ppreq.preq_ttl -= 1; 1138 ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni); 1139 hwmp_send_preq(ni, vap->iv_myaddr, broadcastaddr, 1140 &ppreq); 1141 } 1142 } 1143 } 1144 #undef PREQ_TFLAGS 1145 #undef PREQ_TADDR 1146 #undef PREQ_TSEQ 1147 1148 static int 1149 hwmp_send_preq(struct ieee80211_node *ni, 1150 const uint8_t sa[IEEE80211_ADDR_LEN], 1151 const uint8_t da[IEEE80211_ADDR_LEN], 1152 struct ieee80211_meshpreq_ie *preq) 1153 { 1154 struct ieee80211_hwmp_state *hs = ni->ni_vap->iv_hwmp; 1155 1156 /* 1157 * Enforce PREQ interval. 1158 */ 1159 if (ratecheck(&hs->hs_lastpreq, &ieee80211_hwmp_preqminint) == 0) 1160 return EALREADY; 1161 getmicrouptime(&hs->hs_lastpreq); 1162 1163 /* 1164 * mesh preq action frame format 1165 * [6] da 1166 * [6] sa 1167 * [6] addr3 = sa 1168 * [1] action 1169 * [1] category 1170 * [tlv] mesh path request 1171 */ 1172 preq->preq_ie = IEEE80211_ELEMID_MESHPREQ; 1173 preq->preq_len = (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE ? 1174 IEEE80211_MESHPREQ_BASE_SZ_AE : IEEE80211_MESHPREQ_BASE_SZ) + 1175 preq->preq_tcount * IEEE80211_MESHPREQ_TRGT_SZ; 1176 return hwmp_send_action(ni, sa, da, (uint8_t *)preq, preq->preq_len+2); 1177 } 1178 1179 static void 1180 hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, 1181 const struct ieee80211_frame *wh, const struct ieee80211_meshprep_ie *prep) 1182 { 1183 struct ieee80211_mesh_state *ms = vap->iv_mesh; 1184 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 1185 struct ieee80211_mesh_route *rt = NULL; 1186 struct ieee80211_hwmp_route *hr; 1187 struct ieee80211com *ic = vap->iv_ic; 1188 struct ifnet *ifp = vap->iv_ifp; 1189 struct mbuf *m, *next; 1190 uint32_t metric = 0; 1191 1192 /* 1193 * Acceptance criteria: if the corresponding PREQ was not generated 1194 * by us and forwarding is disabled, discard this PREP. 1195 */ 1196 if (ni == vap->iv_bss || 1197 ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) 1198 return; 1199 if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) && 1200 !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) 1201 return; 1202 1203 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1204 "received PREP from %6D", prep->prep_targetaddr, ":"); 1205 1206 rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr); 1207 if (rt == NULL) { 1208 /* 1209 * If we have no entry this could be a reply to a root PREQ. 1210 * XXX: not true anymore cause we dont create entry for target 1211 * when propagating PREQs like the old code did. 1212 */ 1213 if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) { 1214 rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr); 1215 if (rt == NULL) { 1216 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, 1217 ni, "unable to add PREP path to %6D", 1218 prep->prep_targetaddr, ":"); 1219 vap->iv_stats.is_mesh_rtaddfailed++; 1220 return; 1221 } 1222 IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2); 1223 rt->rt_nhops = prep->prep_hopcount; 1224 rt->rt_lifetime = prep->prep_lifetime; 1225 rt->rt_metric = prep->prep_metric; 1226 rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; 1227 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1228 "add root path to %6D nhops %d metric %lu (PREP)", 1229 prep->prep_targetaddr, ":", 1230 rt->rt_nhops, rt->rt_metric); 1231 return; 1232 } 1233 return; 1234 } 1235 /* 1236 * Sequence number validation. 1237 */ 1238 hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); 1239 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) { 1240 if (HWMP_SEQ_LT(prep->prep_targetseq, hr->hr_seq)) { 1241 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1242 "discard PREP from %6D, old seq no %u < %u", 1243 prep->prep_targetaddr, ":", 1244 prep->prep_targetseq, hr->hr_seq); 1245 return; 1246 } else if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq) && 1247 prep->prep_metric > rt->rt_metric) { 1248 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1249 "discard PREP from %6D, new metric %u > %u", 1250 prep->prep_targetaddr, ":", 1251 prep->prep_metric, rt->rt_metric); 1252 return; 1253 } 1254 } 1255 1256 hr->hr_seq = prep->prep_targetseq; 1257 /* 1258 * If it's NOT for us, propagate the PREP. 1259 */ 1260 if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) && 1261 prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) { 1262 struct ieee80211_meshprep_ie pprep; /* propagated PREP */ 1263 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1264 "propagate PREP from %6D", 1265 prep->prep_targetaddr, ":"); 1266 1267 memcpy(&pprep, prep, sizeof(pprep)); 1268 pprep.prep_hopcount += 1; 1269 pprep.prep_ttl -= 1; 1270 pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni); 1271 hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep); 1272 } 1273 hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); 1274 if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) { 1275 /* NB: never clobber a proxy entry */; 1276 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1277 "discard PREP for %6D, route is marked PROXY", 1278 prep->prep_targetaddr, ":"); 1279 vap->iv_stats.is_hwmp_proxy++; 1280 /* NB: first path discovery always fails */ 1281 } else if (hr->hr_origseq == 0 || 1282 prep->prep_origseq == hr->hr_origseq) { 1283 /* 1284 * Check if we already have a path to this node. 1285 * If we do, check if this path reply contains a 1286 * better route. 1287 */ 1288 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 || 1289 (prep->prep_hopcount < rt->rt_nhops || 1290 prep->prep_metric < rt->rt_metric)) { 1291 hr->hr_origseq = prep->prep_origseq; 1292 metric = prep->prep_metric + 1293 ms->ms_pmetric->mpm_metric(ni); 1294 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1295 "%s path to %6D, hopcount %d:%d metric %d:%d", 1296 rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ? 1297 "prefer" : "update", 1298 prep->prep_origaddr, ":", 1299 rt->rt_nhops, prep->prep_hopcount, 1300 rt->rt_metric, prep->prep_metric); 1301 IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2); 1302 rt->rt_nhops = prep->prep_hopcount + 1; 1303 rt->rt_lifetime = prep->prep_lifetime; 1304 rt->rt_metric = metric; 1305 rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; 1306 } else { 1307 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1308 "ignore PREP for %6D, hopcount %d:%d metric %d:%d", 1309 prep->prep_targetaddr, ":", 1310 rt->rt_nhops, prep->prep_hopcount, 1311 rt->rt_metric, prep->prep_metric); 1312 } 1313 } else { 1314 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1315 "discard PREP for %6D, wrong orig seqno %u != %u", 1316 prep->prep_targetaddr, ":", prep->prep_origseq, 1317 hr->hr_origseq); 1318 vap->iv_stats.is_hwmp_wrongseq++; 1319 } 1320 /* 1321 * Check for frames queued awaiting path discovery. 1322 * XXX probably can tell exactly and avoid remove call 1323 * NB: hash may have false matches, if so they will get 1324 * stuck back on the stageq because there won't be 1325 * a path. 1326 */ 1327 m = ieee80211_ageq_remove(&ic->ic_stageq, 1328 (struct ieee80211_node *)(uintptr_t) 1329 ieee80211_mac_hash(ic, rt->rt_dest)); 1330 for (; m != NULL; m = next) { 1331 next = m->m_nextpkt; 1332 m->m_nextpkt = NULL; 1333 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1334 "flush queued frame %p len %d", m, m->m_pkthdr.len); 1335 ifp->if_transmit(ifp, m); 1336 } 1337 } 1338 1339 static int 1340 hwmp_send_prep(struct ieee80211_node *ni, 1341 const uint8_t sa[IEEE80211_ADDR_LEN], 1342 const uint8_t da[IEEE80211_ADDR_LEN], 1343 struct ieee80211_meshprep_ie *prep) 1344 { 1345 /* NB: there's no PREP minimum interval. */ 1346 1347 /* 1348 * mesh prep action frame format 1349 * [6] da 1350 * [6] sa 1351 * [6] addr3 = sa 1352 * [1] action 1353 * [1] category 1354 * [tlv] mesh path reply 1355 */ 1356 prep->prep_ie = IEEE80211_ELEMID_MESHPREP; 1357 prep->prep_len = prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE ? 1358 IEEE80211_MESHPREP_BASE_SZ_AE : IEEE80211_MESHPREP_BASE_SZ; 1359 return hwmp_send_action(ni, sa, da, (uint8_t *)prep, 1360 prep->prep_len + 2); 1361 } 1362 1363 #define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags 1364 #define PERR_DADDR(n) perr.perr_dests[n].dest_addr 1365 #define PERR_DSEQ(n) perr.perr_dests[n].dest_seq 1366 #define PERR_DRCODE(n) perr.perr_dests[n].dest_rcode 1367 static void 1368 hwmp_peerdown(struct ieee80211_node *ni) 1369 { 1370 struct ieee80211vap *vap = ni->ni_vap; 1371 struct ieee80211_mesh_state *ms = vap->iv_mesh; 1372 struct ieee80211_meshperr_ie perr; 1373 struct ieee80211_mesh_route *rt; 1374 struct ieee80211_hwmp_route *hr; 1375 1376 rt = ieee80211_mesh_rt_find(vap, ni->ni_macaddr); 1377 if (rt == NULL) 1378 return; 1379 hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); 1380 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1381 "%s", "delete route entry"); 1382 perr.perr_ttl = ms->ms_ttl; 1383 perr.perr_ndests = 1; 1384 PERR_DFLAGS(0) = 0; 1385 if (hr->hr_seq == 0) 1386 PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN; 1387 PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC; 1388 IEEE80211_ADDR_COPY(PERR_DADDR(0), rt->rt_dest); 1389 PERR_DSEQ(0) = hr->hr_seq; 1390 PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH; 1391 /* NB: flush everything passing through peer */ 1392 ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr); 1393 hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr); 1394 } 1395 #undef PERR_DFLAGS 1396 #undef PERR_DADDR 1397 #undef PERR_DSEQ 1398 #undef PERR_DRCODE 1399 1400 #define PERR_DFLAGS(n) perr->perr_dests[n].dest_flags 1401 #define PERR_DADDR(n) perr->perr_dests[n].dest_addr 1402 #define PERR_DSEQ(n) perr->perr_dests[n].dest_seq 1403 #define PERR_DRCODE(n) perr->perr_dests[n].dest_rcode 1404 static void 1405 hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, 1406 const struct ieee80211_frame *wh, const struct ieee80211_meshperr_ie *perr) 1407 { 1408 struct ieee80211_mesh_state *ms = vap->iv_mesh; 1409 struct ieee80211_mesh_route *rt = NULL; 1410 struct ieee80211_hwmp_route *hr; 1411 struct ieee80211_meshperr_ie pperr; 1412 int i, forward = 0; 1413 1414 /* 1415 * Acceptance criteria: check if we received a PERR from a 1416 * neighbor and forwarding is enabled. 1417 */ 1418 if (ni == vap->iv_bss || 1419 ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED || 1420 !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) 1421 return; 1422 /* 1423 * Find all routing entries that match and delete them. 1424 */ 1425 for (i = 0; i < perr->perr_ndests; i++) { 1426 rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i)); 1427 if (rt == NULL) 1428 continue; 1429 hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); 1430 if (!(PERR_DFLAGS(0) & IEEE80211_MESHPERR_DFLAGS_USN) && 1431 HWMP_SEQ_GEQ(PERR_DSEQ(i), hr->hr_seq)) { 1432 ieee80211_mesh_rt_del(vap, rt->rt_dest); 1433 ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest); 1434 rt = NULL; 1435 forward = 1; 1436 } 1437 } 1438 /* 1439 * Propagate the PERR if we previously found it on our routing table. 1440 * XXX handle ndest > 1 1441 */ 1442 if (forward && perr->perr_ttl > 1) { 1443 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, 1444 "propagate PERR from %6D", wh->i_addr2, ":"); 1445 memcpy(&pperr, perr, sizeof(*perr)); 1446 pperr.perr_ttl--; 1447 hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, 1448 &pperr); 1449 } 1450 } 1451 #undef PERR_DFLAGS 1452 #undef PEER_DADDR 1453 #undef PERR_DSEQ 1454 #undef PERR_DRCODE 1455 1456 static int 1457 hwmp_send_perr(struct ieee80211_node *ni, 1458 const uint8_t sa[IEEE80211_ADDR_LEN], 1459 const uint8_t da[IEEE80211_ADDR_LEN], 1460 struct ieee80211_meshperr_ie *perr) 1461 { 1462 struct ieee80211_hwmp_state *hs = ni->ni_vap->iv_hwmp; 1463 int i; 1464 uint8_t length = 0; 1465 1466 /* 1467 * Enforce PERR interval. 1468 */ 1469 if (ratecheck(&hs->hs_lastperr, &ieee80211_hwmp_perrminint) == 0) 1470 return EALREADY; 1471 getmicrouptime(&hs->hs_lastperr); 1472 1473 /* 1474 * mesh perr action frame format 1475 * [6] da 1476 * [6] sa 1477 * [6] addr3 = sa 1478 * [1] action 1479 * [1] category 1480 * [tlv] mesh path error 1481 */ 1482 perr->perr_ie = IEEE80211_ELEMID_MESHPERR; 1483 length = IEEE80211_MESHPERR_BASE_SZ; 1484 for (i = 0; i<perr->perr_ndests; i++) { 1485 if (perr->perr_dests[i].dest_flags & 1486 IEEE80211_MESHPERR_FLAGS_AE) { 1487 length += IEEE80211_MESHPERR_DEST_SZ_AE; 1488 continue ; 1489 } 1490 length += IEEE80211_MESHPERR_DEST_SZ; 1491 } 1492 perr->perr_len =length; 1493 return hwmp_send_action(ni, sa, da, (uint8_t *)perr, perr->perr_len+2); 1494 } 1495 1496 static void 1497 hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, 1498 const struct ieee80211_frame *wh, const struct ieee80211_meshrann_ie *rann) 1499 { 1500 struct ieee80211_mesh_state *ms = vap->iv_mesh; 1501 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 1502 struct ieee80211_mesh_route *rt = NULL; 1503 struct ieee80211_hwmp_route *hr; 1504 struct ieee80211_meshrann_ie prann; 1505 1506 if (ni == vap->iv_bss || 1507 ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED || 1508 IEEE80211_ADDR_EQ(rann->rann_addr, vap->iv_myaddr)) 1509 return; 1510 1511 rt = ieee80211_mesh_rt_find(vap, rann->rann_addr); 1512 /* 1513 * Discover the path to the root mesh STA. 1514 * If we already know it, propagate the RANN element. 1515 */ 1516 if (rt == NULL) { 1517 hwmp_discover(vap, rann->rann_addr, NULL); 1518 return; 1519 } 1520 hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); 1521 if (HWMP_SEQ_GT(rann->rann_seq, hr->hr_seq)) { 1522 hr->hr_seq = rann->rann_seq; 1523 if (rann->rann_ttl > 1 && 1524 rann->rann_hopcount < hs->hs_maxhops && 1525 (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) { 1526 memcpy(&prann, rann, sizeof(prann)); 1527 prann.rann_hopcount += 1; 1528 prann.rann_ttl -= 1; 1529 prann.rann_metric += ms->ms_pmetric->mpm_metric(ni); 1530 hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, 1531 broadcastaddr, &prann); 1532 } 1533 } 1534 } 1535 1536 static int 1537 hwmp_send_rann(struct ieee80211_node *ni, 1538 const uint8_t sa[IEEE80211_ADDR_LEN], 1539 const uint8_t da[IEEE80211_ADDR_LEN], 1540 struct ieee80211_meshrann_ie *rann) 1541 { 1542 /* 1543 * mesh rann action frame format 1544 * [6] da 1545 * [6] sa 1546 * [6] addr3 = sa 1547 * [1] action 1548 * [1] category 1549 * [tlv] root annoucement 1550 */ 1551 rann->rann_ie = IEEE80211_ELEMID_MESHRANN; 1552 rann->rann_len = IEEE80211_MESHRANN_BASE_SZ; 1553 return hwmp_send_action(ni, sa, da, (uint8_t *)rann, 1554 rann->rann_len + 2); 1555 } 1556 1557 #define PREQ_TFLAGS(n) preq.preq_targets[n].target_flags 1558 #define PREQ_TADDR(n) preq.preq_targets[n].target_addr 1559 #define PREQ_TSEQ(n) preq.preq_targets[n].target_seq 1560 static struct ieee80211_node * 1561 hwmp_discover(struct ieee80211vap *vap, 1562 const uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m) 1563 { 1564 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 1565 struct ieee80211_mesh_state *ms = vap->iv_mesh; 1566 struct ieee80211_mesh_route *rt = NULL; 1567 struct ieee80211_hwmp_route *hr; 1568 struct ieee80211_meshpreq_ie preq; 1569 struct ieee80211_node *ni; 1570 int sendpreq = 0; 1571 1572 KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, 1573 ("not a mesh vap, opmode %d", vap->iv_opmode)); 1574 1575 KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest), 1576 ("%s: discovering self!", __func__)); 1577 1578 ni = NULL; 1579 if (!IEEE80211_IS_MULTICAST(dest)) { 1580 rt = ieee80211_mesh_rt_find(vap, dest); 1581 if (rt == NULL) { 1582 rt = ieee80211_mesh_rt_add(vap, dest); 1583 if (rt == NULL) { 1584 IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, 1585 ni, "unable to add discovery path to %6D", 1586 dest, ":"); 1587 vap->iv_stats.is_mesh_rtaddfailed++; 1588 goto done; 1589 } 1590 } 1591 hr = IEEE80211_MESH_ROUTE_PRIV(rt, 1592 struct ieee80211_hwmp_route); 1593 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { 1594 if (hr->hr_origseq == 0) 1595 hr->hr_origseq = ++hs->hs_seq; 1596 rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL; 1597 rt->rt_lifetime = 1598 ticks_to_msecs(ieee80211_hwmp_pathtimeout); 1599 /* XXX check preq retries */ 1600 sendpreq = 1; 1601 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, 1602 "start path discovery (src %s), target seq %u", 1603 m == NULL ? "<none>" : ether_sprintf( 1604 mtod(m, struct ether_header *)->ether_shost), 1605 hr->hr_seq); 1606 /* 1607 * Try to discover the path for this node. 1608 * Group addressed PREQ Case A 1609 */ 1610 preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM; 1611 preq.preq_hopcount = 0; 1612 preq.preq_ttl = ms->ms_ttl; 1613 preq.preq_id = ++hs->hs_preqid; 1614 IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr); 1615 preq.preq_origseq = hr->hr_origseq; 1616 preq.preq_lifetime = rt->rt_lifetime; 1617 preq.preq_metric = rt->rt_metric; 1618 preq.preq_tcount = 1; 1619 IEEE80211_ADDR_COPY(PREQ_TADDR(0), dest); 1620 PREQ_TFLAGS(0) = 0; 1621 if (ieee80211_hwmp_targetonly) 1622 PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_TO; 1623 if (ieee80211_hwmp_replyforward) 1624 PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF; 1625 PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN; 1626 PREQ_TSEQ(0) = hr->hr_seq; 1627 /* XXX check return value */ 1628 hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, 1629 broadcastaddr, &preq); 1630 } 1631 if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) 1632 ni = ieee80211_find_txnode(vap, rt->rt_nexthop); 1633 } else { 1634 ni = ieee80211_find_txnode(vap, dest); 1635 /* NB: if null then we leak mbuf */ 1636 KASSERT(ni != NULL, ("leak mcast frame")); 1637 return ni; 1638 } 1639 done: 1640 if (ni == NULL && m != NULL) { 1641 if (sendpreq) { 1642 struct ieee80211com *ic = vap->iv_ic; 1643 /* 1644 * Queue packet for transmit when path discovery 1645 * completes. If discovery never completes the 1646 * frame will be flushed by way of the aging timer. 1647 */ 1648 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, 1649 "%s", "queue frame until path found"); 1650 m->m_pkthdr.rcvif = (void *)(uintptr_t) 1651 ieee80211_mac_hash(ic, dest); 1652 /* XXX age chosen randomly */ 1653 ieee80211_ageq_append(&ic->ic_stageq, m, 1654 IEEE80211_INACT_WAIT); 1655 } else { 1656 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_HWMP, 1657 dest, NULL, "%s", "no valid path to this node"); 1658 m_freem(m); 1659 } 1660 } 1661 return ni; 1662 } 1663 #undef PREQ_TFLAGS 1664 #undef PREQ_TADDR 1665 #undef PREQ_TSEQ 1666 1667 static int 1668 hwmp_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq) 1669 { 1670 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 1671 int error; 1672 1673 if (vap->iv_opmode != IEEE80211_M_MBSS) 1674 return ENOSYS; 1675 error = 0; 1676 switch (ireq->i_type) { 1677 case IEEE80211_IOC_HWMP_ROOTMODE: 1678 ireq->i_val = hs->hs_rootmode; 1679 break; 1680 case IEEE80211_IOC_HWMP_MAXHOPS: 1681 ireq->i_val = hs->hs_maxhops; 1682 break; 1683 default: 1684 return ENOSYS; 1685 } 1686 return error; 1687 } 1688 IEEE80211_IOCTL_GET(hwmp, hwmp_ioctl_get80211); 1689 1690 static int 1691 hwmp_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq) 1692 { 1693 struct ieee80211_hwmp_state *hs = vap->iv_hwmp; 1694 int error; 1695 1696 if (vap->iv_opmode != IEEE80211_M_MBSS) 1697 return ENOSYS; 1698 error = 0; 1699 switch (ireq->i_type) { 1700 case IEEE80211_IOC_HWMP_ROOTMODE: 1701 if (ireq->i_val < 0 || ireq->i_val > 3) 1702 return EINVAL; 1703 hs->hs_rootmode = ireq->i_val; 1704 hwmp_rootmode_setup(vap); 1705 break; 1706 case IEEE80211_IOC_HWMP_MAXHOPS: 1707 if (ireq->i_val <= 0 || ireq->i_val > 255) 1708 return EINVAL; 1709 hs->hs_maxhops = ireq->i_val; 1710 break; 1711 default: 1712 return ENOSYS; 1713 } 1714 return error; 1715 } 1716 IEEE80211_IOCTL_SET(hwmp, hwmp_ioctl_set80211); 1717