File: | src/usr.sbin/hostapd/apme.c |
Warning: | line 178, column 7 Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: apme.c,v 1.17 2019/05/10 01:29:31 guenther Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org> |
5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. |
9 | * |
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ |
18 | |
19 | #include <sys/param.h> /* roundup isclr */ |
20 | #include <sys/ioctl.h> |
21 | #include <sys/socket.h> |
22 | #include <sys/time.h> |
23 | #include <sys/uio.h> |
24 | |
25 | #include <net/if.h> |
26 | #include <net/if_media.h> |
27 | #include <net/if_arp.h> |
28 | #include <net/if_llc.h> |
29 | #include <net/bpf.h> |
30 | |
31 | #include <netinet/in.h> |
32 | #include <netinet/if_ether.h> |
33 | #include <arpa/inet.h> |
34 | |
35 | #include <net80211/ieee80211_radiotap.h> |
36 | |
37 | #include <fcntl.h> |
38 | #include <stdlib.h> |
39 | #include <stdio.h> |
40 | #include <string.h> |
41 | #include <unistd.h> |
42 | #include <limits.h> |
43 | |
44 | #include "hostapd.h" |
45 | #include "iapp.h" |
46 | |
47 | void hostapd_apme_frame(struct hostapd_apme *, u_int8_t *, u_int); |
48 | void hostapd_apme_hopper(int, short, void *); |
49 | |
50 | int |
51 | hostapd_apme_add(struct hostapd_config *cfg, const char *name) |
52 | { |
53 | struct hostapd_apme *apme; |
54 | |
55 | if (hostapd_apme_lookup(cfg, name) != NULL((void *)0)) |
56 | return (EEXIST17); |
57 | if ((apme = (struct hostapd_apme *) |
58 | calloc(1, sizeof(struct hostapd_apme))) == NULL((void *)0)) |
59 | return (ENOMEM12); |
60 | if (strlcpy(apme->a_iface, name, sizeof(apme->a_iface)) >= |
61 | sizeof(apme->a_iface)) { |
62 | free(apme); |
63 | return (EINVAL22); |
64 | } |
65 | |
66 | apme->a_cfg = cfg; |
67 | apme->a_chanavail = NULL((void *)0); |
68 | |
69 | TAILQ_INSERT_TAIL(&cfg->c_apmes, apme, a_entries)do { (apme)->a_entries.tqe_next = ((void *)0); (apme)-> a_entries.tqe_prev = (&cfg->c_apmes)->tqh_last; *(& cfg->c_apmes)->tqh_last = (apme); (&cfg->c_apmes )->tqh_last = &(apme)->a_entries.tqe_next; } while ( 0); |
70 | |
71 | hostapd_log(HOSTAPD_LOG_DEBUG2, |
72 | "%s: Host AP interface added", apme->a_iface); |
73 | |
74 | return (0); |
75 | } |
76 | |
77 | int |
78 | hostapd_apme_deauth(struct hostapd_apme *apme) |
79 | { |
80 | struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg; |
81 | struct hostapd_iapp *iapp = &cfg->c_iapp; |
82 | u_int8_t buf[sizeof(struct ieee80211_frame) + sizeof(u_int16_t)]; |
83 | struct ieee80211_frame *wh; |
84 | |
85 | bzero(&buf, sizeof(buf)); |
86 | wh = (struct ieee80211_frame *)&buf[0]; |
87 | wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_MGT0x00 | |
88 | IEEE80211_FC0_SUBTYPE_DEAUTH0xc0; |
89 | wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00; |
90 | memset(&wh->i_addr1, 0xff, IEEE80211_ADDR_LEN6); |
91 | bcopy(apme->a_bssid, wh->i_addr2, IEEE80211_ADDR_LEN6); |
92 | bcopy(apme->a_bssid, wh->i_addr3, IEEE80211_ADDR_LEN6); |
93 | *(u_int16_t *)(wh + 1) = htole16(IEEE80211_REASON_AUTH_EXPIRE)((__uint16_t)(IEEE80211_REASON_AUTH_EXPIRE)); |
94 | |
95 | if (write(apme->a_raw, buf, sizeof(buf)) == -1) { |
96 | hostapd_log(HOSTAPD_LOG_VERBOSE1, |
97 | "%s/%s: failed to deauthenticate all stations: %s", |
98 | iapp->i_iface, apme->a_iface, |
99 | strerror(errno(*__errno()))); |
100 | return (EIO5); |
101 | } |
102 | |
103 | hostapd_log(HOSTAPD_LOG_VERBOSE1, |
104 | "%s/%s: deauthenticated all stations", |
105 | apme->a_iface, iapp->i_iface); |
106 | |
107 | return (0); |
108 | } |
109 | |
110 | struct hostapd_apme * |
111 | hostapd_apme_lookup(struct hostapd_config *cfg, const char *name) |
112 | { |
113 | struct hostapd_apme *apme; |
114 | |
115 | TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries)for((apme) = ((&cfg->c_apmes)->tqh_first); (apme) != ((void *)0); (apme) = ((apme)->a_entries.tqe_next)) { |
116 | if (strcmp(name, apme->a_iface) == 0) |
117 | return (apme); |
118 | } |
119 | |
120 | return (NULL((void *)0)); |
121 | } |
122 | |
123 | struct hostapd_apme * |
124 | hostapd_apme_addhopper(struct hostapd_config *cfg, const char *name) |
125 | { |
126 | struct hostapd_apme *apme; |
127 | |
128 | if ((apme = hostapd_apme_lookup(cfg, name)) == NULL((void *)0)) |
129 | return (NULL((void *)0)); |
130 | if (apme->a_chanavail != NULL((void *)0)) |
131 | return (NULL((void *)0)); |
132 | apme->a_curchan = IEEE80211_CHAN_MAX255; |
133 | apme->a_maxchan = roundup(IEEE80211_CHAN_MAX, NBBY)((((255)+((8)-1))/(8))*(8)); |
134 | if ((apme->a_chanavail = (u_int8_t *) |
135 | calloc(apme->a_maxchan, sizeof(u_int8_t))) == NULL((void *)0)) |
136 | return (NULL((void *)0)); |
137 | memset(apme->a_chanavail, 0xff, |
138 | apme->a_maxchan * sizeof(u_int8_t)); |
139 | (void)strlcpy(apme->a_chanreq.i_name, apme->a_iface, IFNAMSIZ16); |
140 | |
141 | return (apme); |
142 | } |
143 | |
144 | void |
145 | hostapd_apme_sethopper(struct hostapd_apme *apme, int now) |
146 | { |
147 | struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg; |
148 | struct timeval tv; |
149 | |
150 | bzero(&tv, sizeof(tv)); |
151 | if (!now) |
152 | bcopy(&cfg->c_apme_hopdelay, &tv, sizeof(tv)); |
153 | |
154 | if (!evtimer_initialized(&apme->a_chanev)((&apme->a_chanev)->ev_flags & 0x80)) |
155 | evtimer_set(&apme->a_chanev, hostapd_apme_hopper, apme)event_set(&apme->a_chanev, -1, 0, hostapd_apme_hopper, apme); |
156 | if (evtimer_add(&apme->a_chanev, &tv)event_add(&apme->a_chanev, &tv) == -1) |
157 | hostapd_fatal("failed to add hopper event"); |
158 | } |
159 | |
160 | void |
161 | hostapd_apme_hopper(int fd, short sig, void *arg) |
162 | { |
163 | struct hostapd_apme *apme = (struct hostapd_apme *)arg; |
164 | struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg; |
165 | int ret; |
166 | |
167 | if (apme->a_curchan >= IEEE80211_CHAN_MAX255) |
168 | apme->a_curchan = 0; |
169 | |
170 | do { |
171 | if (apme->a_curchan >= IEEE80211_CHAN_MAX255) |
172 | return; |
173 | apme->a_curchan %= IEEE80211_CHAN_MAX255; |
174 | apme->a_curchan++; |
175 | } while (isclr(apme->a_chanavail, apme->a_curchan)(((apme->a_chanavail)[(apme->a_curchan)>>3] & (1<<((apme->a_curchan)&(8 -1)))) == 0)); |
176 | |
177 | apme->a_chanreq.i_channel = apme->a_curchan; |
178 | if ((ret = ioctl(cfg->c_apme_ctl, SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq ) & 0x1fff) << 16) | ((('i')) << 8) | ((238)) ), |
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret' | |
179 | &apme->a_chanreq)) != 0) { |
180 | hostapd_apme_sethopper(apme, 1); |
181 | return; |
182 | } |
183 | |
184 | hostapd_log(HOSTAPD_LOG_DEBUG2, |
185 | "[priv]: %s setting to channel %d", |
186 | apme->a_iface, apme->a_curchan); |
187 | |
188 | hostapd_apme_sethopper(apme, 0); |
189 | } |
190 | |
191 | void |
192 | hostapd_apme_term(struct hostapd_apme *apme) |
193 | { |
194 | struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg; |
195 | |
196 | /* Remove the channel hopper, if active */ |
197 | if (apme->a_chanavail != NULL((void *)0)) { |
198 | (void)event_del(&apme->a_chanev); |
199 | free(apme->a_chanavail); |
200 | apme->a_chanavail = NULL((void *)0); |
201 | } |
202 | |
203 | /* Kick a specified Host AP interface */ |
204 | (void)event_del(&apme->a_ev); |
205 | if (close(apme->a_raw)) |
206 | hostapd_fatal("failed to close: %s\n", |
207 | strerror(errno(*__errno()))); |
208 | |
209 | TAILQ_REMOVE(&cfg->c_apmes, apme, a_entries)do { if (((apme)->a_entries.tqe_next) != ((void *)0)) (apme )->a_entries.tqe_next->a_entries.tqe_prev = (apme)-> a_entries.tqe_prev; else (&cfg->c_apmes)->tqh_last = (apme)->a_entries.tqe_prev; *(apme)->a_entries.tqe_prev = (apme)->a_entries.tqe_next; ; ; } while (0); |
210 | |
211 | /* Remove all dynamic roaming addresses */ |
212 | if (cfg->c_flags & HOSTAPD_CFG_F_PRIV0x40) |
213 | hostapd_roaming_term(apme); |
214 | |
215 | hostapd_log(HOSTAPD_LOG_DEBUG2, |
216 | "%s: Host AP interface removed", apme->a_iface); |
217 | |
218 | free(apme); |
219 | } |
220 | |
221 | void |
222 | hostapd_apme_input(int fd, short sig, void *arg) |
223 | { |
224 | struct hostapd_apme *apme = (struct hostapd_apme *)arg; |
225 | u_int8_t buf[IAPP_MAXSIZE512], *bp, *ep; |
226 | struct bpf_hdr *bph; |
227 | ssize_t len; |
228 | |
229 | /* Ignore invalid signals */ |
230 | if (sig != EV_READ0x02) |
231 | return; |
232 | |
233 | bzero(&buf, sizeof(buf)); |
234 | |
235 | if ((len = read(fd, buf, sizeof(buf))) < |
236 | (ssize_t)sizeof(struct ieee80211_frame)) |
237 | return; |
238 | |
239 | /* |
240 | * Loop through each frame. |
241 | */ |
242 | |
243 | bp = (u_int8_t *)&buf; |
244 | ep = bp + len; |
245 | |
246 | while (bp < ep) { |
247 | register u_int caplen, hdrlen; |
248 | |
249 | bph = (struct bpf_hdr *)bp; |
250 | caplen = bph->bh_caplen; |
251 | hdrlen = bph->bh_hdrlen; |
252 | |
253 | /* Process frame */ |
254 | hostapd_apme_frame(apme, bp + hdrlen, caplen); |
255 | |
256 | bp += BPF_WORDALIGN(caplen + hdrlen)(((caplen + hdrlen) + (sizeof(u_int32_t) - 1)) & ~(sizeof (u_int32_t) - 1)); |
257 | } |
258 | } |
259 | |
260 | int |
261 | hostapd_apme_output(struct hostapd_apme *apme, |
262 | struct hostapd_ieee80211_frame *frame) |
263 | { |
264 | struct iovec iov[2]; |
265 | int iovcnt; |
266 | struct ieee80211_frame wh; |
267 | |
268 | bzero(&wh, sizeof(wh)); |
269 | |
270 | switch (frame->i_fc[1] & IEEE80211_FC1_DIR_MASK0x03) { |
271 | case IEEE80211_FC1_DIR_NODS0x00: |
272 | bcopy(frame->i_from, wh.i_addr2, IEEE80211_ADDR_LEN6); |
273 | bcopy(frame->i_to, wh.i_addr1, IEEE80211_ADDR_LEN6); |
274 | bcopy(frame->i_bssid, wh.i_addr3, IEEE80211_ADDR_LEN6); |
275 | break; |
276 | case IEEE80211_FC1_DIR_TODS0x01: |
277 | bcopy(frame->i_from, wh.i_addr2, IEEE80211_ADDR_LEN6); |
278 | bcopy(frame->i_to, wh.i_addr3, IEEE80211_ADDR_LEN6); |
279 | bcopy(frame->i_bssid, wh.i_addr1, IEEE80211_ADDR_LEN6); |
280 | break; |
281 | case IEEE80211_FC1_DIR_FROMDS0x02: |
282 | bcopy(frame->i_from, wh.i_addr3, IEEE80211_ADDR_LEN6); |
283 | bcopy(frame->i_to, wh.i_addr1, IEEE80211_ADDR_LEN6); |
284 | bcopy(frame->i_bssid, wh.i_addr2, IEEE80211_ADDR_LEN6); |
285 | break; |
286 | default: |
287 | case IEEE80211_FC1_DIR_DSTODS0x03: |
288 | return (EINVAL22); |
289 | } |
290 | |
291 | wh.i_fc[0] = IEEE80211_FC0_VERSION_00x00 | frame->i_fc[0]; |
292 | wh.i_fc[1] = frame->i_fc[1]; |
293 | bcopy(frame->i_dur, wh.i_dur, sizeof(wh.i_dur)); |
294 | bcopy(frame->i_seq, wh.i_seq, sizeof(wh.i_seq)); |
295 | |
296 | iovcnt = 1; |
297 | iov[0].iov_base = &wh; |
298 | iov[0].iov_len = sizeof(struct ieee80211_frame); |
299 | |
300 | if (frame->i_data != NULL((void *)0) && frame->i_data_len > 0) { |
301 | iovcnt = 2; |
302 | iov[1].iov_base = frame->i_data; |
303 | iov[1].iov_len = frame->i_data_len; |
304 | } |
305 | |
306 | if (writev(apme->a_raw, iov, iovcnt) == -1) |
307 | return (errno(*__errno())); |
308 | |
309 | return (0); |
310 | } |
311 | |
312 | int |
313 | hostapd_apme_offset(struct hostapd_apme *apme, |
314 | u_int8_t *buf, const u_int len) |
315 | { |
316 | struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg; |
317 | struct ieee80211_radiotap_header *rh; |
318 | u_int rh_len; |
319 | |
320 | if (cfg->c_apme_dlt == DLT_IEEE802_11105) |
321 | return (0); |
322 | else if (cfg->c_apme_dlt != DLT_IEEE802_11_RADIO127) |
323 | return (-1); |
324 | |
325 | if (len < sizeof(struct ieee80211_radiotap_header)) |
326 | return (-1); |
327 | |
328 | rh = (struct ieee80211_radiotap_header*)buf; |
329 | rh_len = letoh16(rh->it_len)((__uint16_t)(rh->it_len)); |
330 | |
331 | if (rh->it_version != 0) |
332 | return (-1); |
333 | if (len <= rh_len) |
334 | return (-1); |
335 | |
336 | return ((int)rh_len); |
337 | } |
338 | |
339 | void |
340 | hostapd_apme_frame(struct hostapd_apme *apme, u_int8_t *buf, u_int len) |
341 | { |
342 | struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg; |
343 | struct hostapd_iapp *iapp = &cfg->c_iapp; |
344 | struct hostapd_apme *other_apme; |
345 | struct hostapd_node node; |
346 | struct ieee80211_frame *wh; |
347 | int offset; |
348 | |
349 | if ((offset = hostapd_apme_offset(apme, buf, len)) < 0) |
350 | return; |
351 | wh = (struct ieee80211_frame *)(buf + offset); |
352 | |
353 | /* Ignore short frames or fragments */ |
354 | if (len < sizeof(struct ieee80211_frame)) |
355 | return; |
356 | |
357 | /* Handle received frames */ |
358 | if ((hostapd_handle_input(apme, buf, len) == |
359 | (HOSTAPD_FRAME_F_RET_SKIP0x20000000 >> HOSTAPD_FRAME_F_RET_S28)) || |
360 | cfg->c_flags & HOSTAPD_CFG_F_IAPP_PASSIVE0x04) |
361 | return; |
362 | |
363 | /* |
364 | * Only accept local association response frames, ... |
365 | */ |
366 | if (!((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK0x03) == |
367 | IEEE80211_FC1_DIR_NODS0x00 && |
368 | (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) == |
369 | IEEE80211_FC0_TYPE_MGT0x00 && |
370 | (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK0xf0) == |
371 | IEEE80211_FC0_SUBTYPE_ASSOC_RESP0x10)) |
372 | return; |
373 | |
374 | /* |
375 | * ...sent by the Host AP (addr2) to our BSSID (addr3) |
376 | */ |
377 | if (bcmp(wh->i_addr2, apme->a_bssid, IEEE80211_ADDR_LEN6) != 0 || |
378 | bcmp(wh->i_addr3, apme->a_bssid, IEEE80211_ADDR_LEN6) != 0) |
379 | return; |
380 | |
381 | cfg->c_stats.cn_rx_apme++; |
382 | |
383 | /* |
384 | * Double-check if the station got associated to our Host AP |
385 | */ |
386 | bcopy(wh->i_addr1, node.ni_macaddr, IEEE80211_ADDR_LEN6); |
387 | if (hostapd_priv_apme_getnode(apme, &node) != 0) { |
388 | hostapd_log(HOSTAPD_LOG_DEBUG2, |
389 | "%s: invalid association from %s on the Host AP", |
390 | apme->a_iface, etheraddr_string(wh->i_addr1)ether_ntoa((struct ether_addr*)wh->i_addr1)); |
391 | return; |
392 | } |
393 | cfg->c_stats.cn_tx_apme++; |
394 | |
395 | /* |
396 | * Delete node on other attached Host APs |
397 | */ |
398 | TAILQ_FOREACH(other_apme, &cfg->c_apmes, a_entries)for((other_apme) = ((&cfg->c_apmes)->tqh_first); (other_apme ) != ((void *)0); (other_apme) = ((other_apme)->a_entries. tqe_next)) { |
399 | if (apme == other_apme) |
400 | continue; |
401 | if (iapp->i_flags & HOSTAPD_IAPP_F_ROAMING(0x08 | 0x04)) |
402 | (void)hostapd_roaming_del(other_apme, &node); |
403 | if (hostapd_apme_delnode(other_apme, &node) == 0) |
404 | cfg->c_stats.cn_tx_apme++; |
405 | } |
406 | |
407 | if (iapp->i_flags & HOSTAPD_IAPP_F_ROAMING(0x08 | 0x04)) |
408 | (void)hostapd_roaming_add(apme, &node); |
409 | |
410 | (void)hostapd_iapp_add_notify(apme, &node); |
411 | } |
412 | |
413 | void |
414 | hostapd_apme_init(struct hostapd_apme *apme) |
415 | { |
416 | struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg; |
417 | u_int i, dlt; |
418 | struct ifreq ifr; |
419 | |
420 | apme->a_raw = hostapd_bpf_open(O_RDWR0x0002); |
421 | |
422 | apme->a_rawlen = IAPP_MAXSIZE512; |
423 | if (ioctl(apme->a_raw, BIOCSBLEN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (u_int) & 0x1fff) << 16) | ((('B')) << 8) | ( (102))), &apme->a_rawlen) == -1) |
424 | hostapd_fatal("failed to set BPF buffer len \"%s\": %s\n", |
425 | apme->a_iface, strerror(errno(*__errno()))); |
426 | |
427 | i = 1; |
428 | if (ioctl(apme->a_raw, BIOCIMMEDIATE((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('B')) << 8) | ((112))), &i) == -1) |
429 | hostapd_fatal("failed to set BPF immediate mode on \"%s\": " |
430 | "%s\n", apme->a_iface, strerror(errno(*__errno()))); |
431 | |
432 | bzero(&ifr, sizeof(struct ifreq)); |
433 | (void)strlcpy(ifr.ifr_name, apme->a_iface, sizeof(ifr.ifr_name)); |
434 | |
435 | /* This may fail, ignore it */ |
436 | (void)ioctl(apme->a_raw, BIOCPROMISC((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('B')) << 8) | ((105))), NULL((void *)0)); |
437 | |
438 | /* Associate the wireless network interface to the BPF descriptor */ |
439 | if (ioctl(apme->a_raw, BIOCSETIF((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('B')) << 8) | ((108))), &ifr) == -1) |
440 | hostapd_fatal("failed to set BPF interface \"%s\": %s\n", |
441 | apme->a_iface, strerror(errno(*__errno()))); |
442 | |
443 | dlt = cfg->c_apme_dlt; |
444 | if (ioctl(apme->a_raw, BIOCSDLT((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('B')) << 8) | ((122))), &dlt) == -1) |
445 | hostapd_fatal("failed to set BPF link type on \"%s\": %s\n", |
446 | apme->a_iface, strerror(errno(*__errno()))); |
447 | |
448 | /* Lock the BPF descriptor, no further configuration */ |
449 | if (ioctl(apme->a_raw, BIOCLOCK((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) | ((('B')) << 8) | ((118))), NULL((void *)0)) == -1) |
450 | hostapd_fatal("failed to lock BPF interface on \"%s\": %s\n", |
451 | apme->a_iface, strerror(errno(*__errno()))); |
452 | } |
453 | |
454 | int |
455 | hostapd_apme_addnode(struct hostapd_apme *apme, struct hostapd_node *node) |
456 | { |
457 | return (hostapd_priv_apme_setnode(apme, node, 1)); |
458 | } |
459 | |
460 | int |
461 | hostapd_apme_delnode(struct hostapd_apme *apme, struct hostapd_node *node) |
462 | { |
463 | return (hostapd_priv_apme_setnode(apme, node, 0)); |
464 | } |