ieee80211_output.c revision 1.3 1 /*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * Alternatively, this software may be distributed under the terms of the
18 * GNU General Public License ("GPL") version 2 as published by the Free
19 * Software Foundation.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.5 2003/09/01 02:55:09 sam Exp $");
35
36 #include "opt_inet.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/mbuf.h>
41 #include <sys/malloc.h>
42 #include <sys/kernel.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <sys/endian.h>
46 #include <sys/errno.h>
47 #include <sys/bus.h>
48 #include <sys/proc.h>
49 #include <sys/sysctl.h>
50
51 #ifdef __FreeBSD__
52 #include <machine/atomic.h>
53 #endif
54
55 #include <net/if.h>
56 #include <net/if_dl.h>
57 #include <net/if_media.h>
58 #include <net/if_arp.h>
59 #ifdef __FreeBSD__
60 #include <net/ethernet.h>
61 #endif
62 #include <net/if_llc.h>
63
64 #include <net80211/ieee80211_compat.h>
65 #include <net80211/ieee80211_var.h>
66
67 #include <net/bpf.h>
68
69 #ifdef INET
70 #include <netinet/in.h>
71 #include <netinet/if_ether.h>
72 #endif
73
74 /*
75 * Send a management frame to the specified node. The node pointer
76 * must have a reference as the pointer will be passed to the driver
77 * and potentially held for a long time. If the frame is successfully
78 * dispatched to the driver, then it is responsible for freeing the
79 * reference (and potentially free'ing up any associated storage).
80 */
81 static int
82 ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
83 struct mbuf *m, int type)
84 {
85 struct ieee80211com *ic = (void *)ifp;
86 struct ieee80211_frame *wh;
87
88 KASSERT(ni != NULL, ("null node"));
89 ni->ni_inact = 0;
90
91 /*
92 * Yech, hack alert! We want to pass the node down to the
93 * driver's start routine. If we don't do so then the start
94 * routine must immediately look it up again and that can
95 * cause a lock order reversal if, for example, this frame
96 * is being sent because the station is being timedout and
97 * the frame being sent is a DEAUTH message. We could stick
98 * this in an m_tag and tack that on to the mbuf. However
99 * that's rather expensive to do for every frame so instead
100 * we stuff it in the rcvif field since outbound frames do
101 * not (presently) use this.
102 */
103 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
104 if (m == NULL)
105 return ENOMEM;
106 KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null"));
107 m->m_pkthdr.rcvif = (void *)ni;
108
109 wh = mtod(m, struct ieee80211_frame *);
110 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type;
111 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
112 *(u_int16_t *)&wh->i_dur[0] = 0;
113 *(u_int16_t *)&wh->i_seq[0] =
114 htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
115 ni->ni_txseq++;
116 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr);
117 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
118 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
119
120 if (ifp->if_flags & IFF_DEBUG) {
121 /* avoid to print too many frames */
122 if (ic->ic_opmode == IEEE80211_M_IBSS ||
123 #ifdef IEEE80211_DEBUG
124 ieee80211_debug > 1 ||
125 #endif
126 (type & IEEE80211_FC0_SUBTYPE_MASK) !=
127 IEEE80211_FC0_SUBTYPE_PROBE_RESP)
128 if_printf(ifp, "sending %s to %s on channel %u\n",
129 ieee80211_mgt_subtype_name[
130 (type & IEEE80211_FC0_SUBTYPE_MASK)
131 >> IEEE80211_FC0_SUBTYPE_SHIFT],
132 ether_sprintf(ni->ni_macaddr),
133 ieee80211_chan2ieee(ic, ni->ni_chan));
134 }
135
136 IF_ENQUEUE(&ic->ic_mgtq, m);
137 ifp->if_timer = 1;
138 (*ifp->if_start)(ifp);
139 return 0;
140 }
141
142 /*
143 * Encapsulate an outbound data frame. The mbuf chain is updated and
144 * a reference to the destination node is returned. If an error is
145 * encountered NULL is returned and the node reference will also be NULL.
146 *
147 * NB: The caller is responsible for free'ing a returned node reference.
148 * The convention is ic_bss is not reference counted; the caller must
149 * maintain that.
150 */
151 struct mbuf *
152 ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
153 {
154 struct ieee80211com *ic = (void *)ifp;
155 struct ether_header eh;
156 struct ieee80211_frame *wh;
157 struct ieee80211_node *ni = NULL;
158 struct llc *llc;
159
160 if (m->m_len < sizeof(struct ether_header)) {
161 m = m_pullup(m, sizeof(struct ether_header));
162 if (m == NULL) {
163 /* XXX statistic */
164 goto bad;
165 }
166 }
167 memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
168
169 if (ic->ic_opmode != IEEE80211_M_STA) {
170 ni = ieee80211_find_node(ic, eh.ether_dhost);
171 if (ni == NULL) {
172 /*
173 * When not in station mode the
174 * destination address should always be
175 * in the node table unless this is a
176 * multicast/broadcast frame.
177 */
178 if (!IEEE80211_IS_MULTICAST(eh.ether_dhost)) {
179 /* ic->ic_stats.st_tx_nonode++; XXX statistic */
180 goto bad;
181 }
182 ni = ic->ic_bss;
183 }
184 } else
185 ni = ic->ic_bss;
186 ni->ni_inact = 0;
187
188 m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
189 llc = mtod(m, struct llc *);
190 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
191 llc->llc_control = LLC_UI;
192 llc->llc_snap.org_code[0] = 0;
193 llc->llc_snap.org_code[1] = 0;
194 llc->llc_snap.org_code[2] = 0;
195 llc->llc_snap.ether_type = eh.ether_type;
196 M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
197 if (m == NULL)
198 goto bad;
199 wh = mtod(m, struct ieee80211_frame *);
200 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
201 *(u_int16_t *)&wh->i_dur[0] = 0;
202 *(u_int16_t *)&wh->i_seq[0] =
203 htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT);
204 ni->ni_txseq++;
205 switch (ic->ic_opmode) {
206 case IEEE80211_M_STA:
207 wh->i_fc[1] = IEEE80211_FC1_DIR_TODS;
208 IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid);
209 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
210 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost);
211 break;
212 case IEEE80211_M_IBSS:
213 case IEEE80211_M_AHDEMO:
214 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
215 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
216 IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost);
217 IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
218 break;
219 case IEEE80211_M_HOSTAP:
220 wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
221 IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost);
222 IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid);
223 IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost);
224 break;
225 case IEEE80211_M_MONITOR:
226 goto bad;
227 }
228 *pni = ni;
229 return m;
230 bad:
231 if (m != NULL)
232 m_freem(m);
233 if (ni && ni != ic->ic_bss)
234 ieee80211_free_node(ic, ni);
235 *pni = NULL;
236 return NULL;
237 }
238
239 /*
240 * Add a supported rates element id to a frame.
241 */
242 u_int8_t *
243 ieee80211_add_rates(u_int8_t *frm, const struct ieee80211_rateset *rs)
244 {
245 int nrates;
246
247 *frm++ = IEEE80211_ELEMID_RATES;
248 nrates = rs->rs_nrates;
249 if (nrates > IEEE80211_RATE_SIZE)
250 nrates = IEEE80211_RATE_SIZE;
251 *frm++ = nrates;
252 memcpy(frm, rs->rs_rates, nrates);
253 return frm + nrates;
254 }
255
256 /*
257 * Add an extended supported rates element id to a frame.
258 */
259 u_int8_t *
260 ieee80211_add_xrates(u_int8_t *frm, const struct ieee80211_rateset *rs)
261 {
262 /*
263 * Add an extended supported rates element if operating in 11g mode.
264 */
265 if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
266 int nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
267 *frm++ = IEEE80211_ELEMID_XRATES;
268 *frm++ = nrates;
269 memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
270 frm += nrates;
271 }
272 return frm;
273 }
274
275 /*
276 * Add an ssid elemet to a frame.
277 */
278 static u_int8_t *
279 ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
280 {
281 *frm++ = IEEE80211_ELEMID_SSID;
282 *frm++ = len;
283 memcpy(frm, ssid, len);
284 return frm + len;
285 }
286
287 static struct mbuf *
288 ieee80211_getmbuf(int flags, int type, u_int pktlen)
289 {
290 struct mbuf *m;
291
292 KASSERT(pktlen <= MCLBYTES, ("802.11 packet too large: %u", pktlen));
293 #ifdef __FreeBSD__
294 if (pktlen <= MHLEN)
295 MGETHDR(m, flags, type);
296 else
297 m = m_getcl(flags, type, M_PKTHDR);
298 #else
299 MGETHDR(m, flags, type);
300 if (m != NULL && pktlen > MHLEN)
301 MCLGET(m, flags);
302 #endif
303 return m;
304 }
305
306 /*
307 * Send a management frame. The node is for the destination (or ic_bss
308 * when in station mode). Nodes other than ic_bss have their reference
309 * count bumped to reflect our use for an indeterminant time.
310 */
311 int
312 ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
313 int type, int arg)
314 {
315 #define senderr(_x) do { ret = _x; goto bad; } while (0)
316 struct ifnet *ifp = &ic->ic_if;
317 struct mbuf *m;
318 u_int8_t *frm;
319 enum ieee80211_phymode mode;
320 u_int16_t capinfo;
321 int ret, timer;
322
323 KASSERT(ni != NULL, ("null node"));
324
325 /*
326 * Hold a reference on the node so it doesn't go away until after
327 * the xmit is complete all the way in the driver. On error we
328 * will remove our reference.
329 */
330 if (ni != ic->ic_bss)
331 ieee80211_ref_node(ni);
332 timer = 0;
333 switch (type) {
334 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
335 /*
336 * prreq frame format
337 * [tlv] ssid
338 * [tlv] supported rates
339 * [tlv] extended supported rates
340 */
341 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
342 2 + ic->ic_des_esslen
343 + 2 + IEEE80211_RATE_SIZE
344 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
345 if (m == NULL)
346 senderr(ENOMEM);
347 m->m_data += sizeof(struct ieee80211_frame);
348 frm = mtod(m, u_int8_t *);
349 frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
350 mode = ieee80211_chan2mode(ic, ni->ni_chan);
351 frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);
352 frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);
353 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
354
355 timer = IEEE80211_TRANS_WAIT;
356 break;
357
358 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
359 /*
360 * probe response frame format
361 * [8] time stamp
362 * [2] beacon interval
363 * [2] cabability information
364 * [tlv] ssid
365 * [tlv] supported rates
366 * [tlv] parameter set (IBSS)
367 * [tlv] extended supported rates
368 */
369 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
370 8 + 2 + 2 + 2
371 + 2 + ni->ni_esslen
372 + 2 + IEEE80211_RATE_SIZE
373 + 6
374 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
375 if (m == NULL)
376 senderr(ENOMEM);
377 m->m_data += sizeof(struct ieee80211_frame);
378 frm = mtod(m, u_int8_t *);
379
380 memset(frm, 0, 8); /* timestamp should be filled later */
381 frm += 8;
382 *(u_int16_t *)frm = htole16(ic->ic_bss->ni_intval);
383 frm += 2;
384 if (ic->ic_opmode == IEEE80211_M_IBSS)
385 capinfo = IEEE80211_CAPINFO_IBSS;
386 else
387 capinfo = IEEE80211_CAPINFO_ESS;
388 if (ic->ic_flags & IEEE80211_F_WEPON)
389 capinfo |= IEEE80211_CAPINFO_PRIVACY;
390 *(u_int16_t *)frm = htole16(capinfo);
391 frm += 2;
392
393 frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,
394 ic->ic_bss->ni_esslen);
395 frm = ieee80211_add_rates(frm, &ic->ic_bss->ni_rates);
396
397 if (ic->ic_opmode == IEEE80211_M_IBSS) {
398 *frm++ = IEEE80211_ELEMID_IBSSPARMS;
399 *frm++ = 2;
400 *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */
401 } else { /* IEEE80211_M_HOSTAP */
402 /* TODO: TIM */
403 *frm++ = IEEE80211_ELEMID_TIM;
404 *frm++ = 4; /* length */
405 *frm++ = 0; /* DTIM count */
406 *frm++ = 1; /* DTIM period */
407 *frm++ = 0; /* bitmap control */
408 *frm++ = 0; /* Partial Virtual Bitmap (variable length) */
409 }
410 frm = ieee80211_add_xrates(frm, &ic->ic_bss->ni_rates);
411 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
412 break;
413
414 case IEEE80211_FC0_SUBTYPE_AUTH:
415 MGETHDR(m, M_DONTWAIT, MT_DATA);
416 if (m == NULL)
417 senderr(ENOMEM);
418 MH_ALIGN(m, 2 * 3);
419 m->m_pkthdr.len = m->m_len = 6;
420 frm = mtod(m, u_int8_t *);
421 /* TODO: shared key auth */
422 ((u_int16_t *)frm)[0] = htole16(IEEE80211_AUTH_ALG_OPEN);
423 ((u_int16_t *)frm)[1] = htole16(arg); /* sequence number */
424 ((u_int16_t *)frm)[2] = 0; /* status */
425 if (ic->ic_opmode == IEEE80211_M_STA)
426 timer = IEEE80211_TRANS_WAIT;
427 break;
428
429 case IEEE80211_FC0_SUBTYPE_DEAUTH:
430 if (ifp->if_flags & IFF_DEBUG)
431 if_printf(ifp, "station %s deauthenticate (reason %d)\n",
432 ether_sprintf(ni->ni_macaddr), arg);
433 MGETHDR(m, M_DONTWAIT, MT_DATA);
434 if (m == NULL)
435 senderr(ENOMEM);
436 MH_ALIGN(m, 2);
437 m->m_pkthdr.len = m->m_len = 2;
438 *mtod(m, u_int16_t *) = htole16(arg); /* reason */
439 break;
440
441 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
442 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
443 /*
444 * asreq frame format
445 * [2] capability information
446 * [2] listen interval
447 * [6*] current AP address (reassoc only)
448 * [tlv] ssid
449 * [tlv] supported rates
450 * [tlv] extended supported rates
451 */
452 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
453 sizeof(capinfo)
454 + sizeof(u_int16_t)
455 + IEEE80211_ADDR_LEN
456 + 2 + ni->ni_esslen
457 + 2 + IEEE80211_RATE_SIZE
458 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
459 if (m == NULL)
460 senderr(ENOMEM);
461 m->m_data += sizeof(struct ieee80211_frame);
462 frm = mtod(m, u_int8_t *);
463
464 capinfo = 0;
465 if (ic->ic_opmode == IEEE80211_M_IBSS)
466 capinfo |= IEEE80211_CAPINFO_IBSS;
467 else /* IEEE80211_M_STA */
468 capinfo |= IEEE80211_CAPINFO_ESS;
469 if (ic->ic_flags & IEEE80211_F_WEPON)
470 capinfo |= IEEE80211_CAPINFO_PRIVACY;
471 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
472 capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
473 if (ic->ic_flags & IEEE80211_F_SHSLOT)
474 capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
475 *(u_int16_t *)frm = htole16(capinfo);
476 frm += 2;
477
478 *(u_int16_t *)frm = htole16(ic->ic_lintval);
479 frm += 2;
480
481 if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
482 IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid);
483 frm += IEEE80211_ADDR_LEN;
484 }
485
486 frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen);
487 frm = ieee80211_add_rates(frm, &ni->ni_rates);
488 frm = ieee80211_add_xrates(frm, &ni->ni_rates);
489 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
490
491 timer = IEEE80211_TRANS_WAIT;
492 break;
493
494 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
495 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
496 /*
497 * asreq frame format
498 * [2] capability information
499 * [2] status
500 * [2] association ID
501 * [tlv] supported rates
502 * [tlv] extended supported rates
503 */
504 m = ieee80211_getmbuf(M_DONTWAIT, MT_DATA,
505 sizeof(capinfo)
506 + sizeof(u_int16_t)
507 + sizeof(u_int16_t)
508 + 2 + IEEE80211_RATE_SIZE
509 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
510 if (m == NULL)
511 senderr(ENOMEM);
512 m->m_data += sizeof(struct ieee80211_frame);
513 frm = mtod(m, u_int8_t *);
514
515 capinfo = IEEE80211_CAPINFO_ESS;
516 if (ic->ic_flags & IEEE80211_F_WEPON)
517 capinfo |= IEEE80211_CAPINFO_PRIVACY;
518 *(u_int16_t *)frm = htole16(capinfo);
519 frm += 2;
520
521 *(u_int16_t *)frm = htole16(arg); /* status */
522 frm += 2;
523
524 if (arg == IEEE80211_STATUS_SUCCESS)
525 *(u_int16_t *)frm = htole16(ni->ni_associd);
526 frm += 2;
527
528 frm = ieee80211_add_rates(frm, &ni->ni_rates);
529 frm = ieee80211_add_xrates(frm, &ni->ni_rates);
530 m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
531 break;
532
533 case IEEE80211_FC0_SUBTYPE_DISASSOC:
534 if (ifp->if_flags & IFF_DEBUG)
535 if_printf(ifp, "station %s disassociate (reason %d)\n",
536 ether_sprintf(ni->ni_macaddr), arg);
537 MGETHDR(m, M_DONTWAIT, MT_DATA);
538 if (m == NULL)
539 senderr(ENOMEM);
540 MH_ALIGN(m, 2);
541 m->m_pkthdr.len = m->m_len = 2;
542 *mtod(m, u_int16_t *) = htole16(arg); /* reason */
543 break;
544
545 default:
546 IEEE80211_DPRINTF(("%s: invalid mgmt frame type %u\n",
547 __func__, type));
548 senderr(EINVAL);
549 /* NOTREACHED */
550 }
551
552 ret = ieee80211_mgmt_output(ifp, ni, m, type);
553 if (ret == 0) {
554 if (timer)
555 ic->ic_mgt_timer = timer;
556 } else {
557 bad:
558 if (ni != ic->ic_bss) /* remove ref we added */
559 ieee80211_free_node(ic, ni);
560 }
561 return ret;
562 #undef senderr
563 }
564