| 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 | } |