static void acs_clean_chan_surveys(struct hostapd_channel_data *chan) { struct freq_survey *survey, *tmp; if (dl_list_empty(&chan->survey_list)) return; dl_list_for_each_safe(survey, tmp, &chan->survey_list, struct freq_survey, list) { dl_list_del(&survey->list); os_free(survey); } }
void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx) { if (er == NULL) return; http_server_deinit(er->http_srv); wps_er_ap_remove_all(er); wps_er_ssdp_deinit(er); eloop_register_timeout(dl_list_empty(&er->ap_unsubscribing) ? 0 : 5, 0, wps_er_deinit_finish, er, NULL); wpa_printf(MSG_DEBUG, "WPS ER: Finish deinit from timeout"); er->deinitializing = 1; er->deinit_done_cb = cb; er->deinit_done_ctx = ctx; }
static void hostapd_update_nf(struct hostapd_iface *iface, struct hostapd_channel_data *chan, struct freq_survey *survey) { if (!iface->chans_surveyed) { chan->min_nf = survey->nf; iface->lowest_nf = survey->nf; } else { if (dl_list_empty(&chan->survey_list)) chan->min_nf = survey->nf; else if (survey->nf < chan->min_nf) chan->min_nf = survey->nf; if (survey->nf < iface->lowest_nf) iface->lowest_nf = survey->nf; } }
/** * upnp_wps_device_send_event - Queue event messages for subscribers * @sm: WPS UPnP state machine from upnp_wps_device_init() * * This function queues the last WLANEvent to be sent for all currently * subscribed UPnP control points. sm->wlanevent must have been set with the * encoded data before calling this function. */ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm) { /* Enqueue event message for all subscribers */ struct wpabuf *buf; /* holds event message */ int buf_size = 0; struct subscription *s, *tmp; /* Actually, utf-8 is the default, but it doesn't hurt to specify it */ const char *format_head = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n"; const char *format_tail = "</e:propertyset>\n"; if (dl_list_empty(&sm->subscriptions)) { /* optimize */ return; } /* Determine buffer size needed first */ buf_size += os_strlen(format_head); buf_size += 50 + 2 * os_strlen("WLANEvent"); if (sm->wlanevent) buf_size += os_strlen(sm->wlanevent); buf_size += os_strlen(format_tail); buf = wpabuf_alloc(buf_size); if (buf == NULL) return; wpabuf_put_str(buf, format_head); wpabuf_put_property(buf, "WLANEvent", sm->wlanevent); wpabuf_put_str(buf, format_tail); wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s", (char *) wpabuf_head(buf)); dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription, list) { if (event_add(s, buf)) { wpa_printf(MSG_INFO, "WPS UPnP: Dropping " "subscriber due to event backlog"); dl_list_del(&s->list); subscription_destroy(s); } } wpabuf_free(buf); }
static void wpas_ctrl_msg_send_pending_iface(struct wpa_supplicant *wpa_s) { struct ctrl_iface_priv *priv; struct ctrl_iface_msg *msg; priv = wpa_s->ctrl_iface; while (priv && !dl_list_empty(&priv->msg_queue) && !wpas_ctrl_iface_throttle(priv->sock)) { msg = dl_list_first(&priv->msg_queue, struct ctrl_iface_msg, list); if (!msg) break; dl_list_del(&msg->list); wpa_supplicant_ctrl_iface_send(wpa_s, NULL, priv->sock, &priv->ctrl_dst, msg->level, msg->txt, msg->len, priv, NULL); os_free(msg); } }
static void acs_survey_chan_interference_factor(struct hostapd_iface *iface, struct hostapd_channel_data *chan) { struct freq_survey *survey; unsigned int i = 0; long double int_factor = 0; unsigned count = 0; if (dl_list_empty(&chan->survey_list)) return; if (chan->flag & HOSTAPD_CHAN_DISABLED) return; chan->interference_factor = 0; dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list) { i++; if (!acs_survey_is_sufficient(survey)) { wpa_printf(MSG_DEBUG, "ACS: %d: insufficient data", i); continue; } count++; int_factor = acs_survey_interference_factor(survey, iface->lowest_nf); chan->interference_factor += int_factor; wpa_printf(MSG_DEBUG, "ACS: %d: min_nf=%d interference_factor=%Lg nf=%d time=%lu busy=%lu rx=%lu", i, chan->min_nf, int_factor, survey->nf, (unsigned long) survey->channel_time, (unsigned long) survey->channel_time_busy, (unsigned long) survey->channel_time_rx); } if (!count) return; chan->interference_factor /= count; }
/* event_send_all_later_handler -- actually send events as needed */ static void event_send_all_later_handler(void *eloop_data, void *user_ctx) { struct upnp_wps_device_sm *sm = user_ctx; struct subscription *s, *tmp; int nerrors = 0; sm->event_send_all_queued = 0; dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription, list) { if (s->current_event == NULL /* not busy */ && !dl_list_empty(&s->event_queue) /* more to do */) { if (event_send_start(s)) nerrors++; } } if (nerrors) { /* Try again later */ event_send_all_later(sm); } }
/** * wpa_bss_flush_by_age - Flush old BSS entries * @wpa_s: Pointer to wpa_supplicant data * @age: Maximum entry age in seconds * * Remove BSS entries that have not been updated during the last @age seconds. */ void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age) { struct wpa_bss *bss, *n; struct os_reltime t; if (dl_list_empty(&wpa_s->bss)) return; os_get_reltime(&t); t.sec -= age; dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { if (wpa_bss_in_use(wpa_s, bss)) continue; if (os_reltime_before(&bss->last_update, &t)) { wpa_bss_remove(wpa_s, bss, __func__); } else break; } }
static void wpas_ctrl_msg_send_pending_global(struct wpa_global *global) { struct ctrl_iface_global_priv *gpriv; struct ctrl_iface_msg *msg; gpriv = global->ctrl_iface; while (gpriv && !dl_list_empty(&gpriv->msg_queue) && !wpas_ctrl_iface_throttle(gpriv->sock)) { msg = dl_list_first(&gpriv->msg_queue, struct ctrl_iface_msg, list); if (!msg) break; dl_list_del(&msg->list); wpa_supplicant_ctrl_iface_send( msg->wpa_s, msg->type != WPA_MSG_PER_INTERFACE ? NULL : msg->wpa_s->ifname, gpriv->sock, &gpriv->ctrl_dst, msg->level, msg->txt, msg->len, NULL, gpriv); os_free(msg); } }
static void event_addr_failure(struct wps_event_ *e) { struct subscription *s = e->s; e->addr->num_failures++; wpa_printf(MSG_DEBUG, "WPS UPnP: Failed to send event %p to %s " "(num_failures=%u)", e, e->addr->domain_and_port, e->addr->num_failures); if (e->addr->num_failures < MAX_FAILURES) { /* Try other addresses, if available */ event_retry(e, 1); return; } /* * If other side doesn't like what we say, forget about them. * (There is no way to tell other side that we are dropping them...). */ wpa_printf(MSG_DEBUG, "WPS UPnP: Deleting subscription %p " "address %s due to errors", s, e->addr->domain_and_port); dl_list_del(&e->addr->list); subscr_addr_delete(e->addr); e->addr = NULL; if (dl_list_empty(&s->addr_list)) { /* if we've given up on all addresses */ wpa_printf(MSG_DEBUG, "WPS UPnP: Removing subscription %p " "with no addresses", s); dl_list_del(&s->list); subscription_destroy(s); return; } /* Try other addresses, if available */ event_retry(e, 0); }
err_t tls_netif_remove_status_event(tls_netif_status_event_fn event_fn) { struct tls_netif_status_event *status_event; bool is_exist = FALSE; u32 cpu_sr; if(dl_list_empty(&netif_status_event.list)) return 0; dl_list_for_each(status_event, &netif_status_event.list, struct tls_netif_status_event, list) { if(status_event->status_callback == event_fn) { is_exist = TRUE; break; } } if(is_exist) { cpu_sr = tls_os_set_critical(); dl_list_del(&status_event->list); tls_os_release_critical(cpu_sr); tls_mem_free(status_event); } return 0; }
void eloop_run(void) { #ifdef CONFIG_ELOOP_POLL int num_poll_fds; int timeout_ms = 0; #endif /* CONFIG_ELOOP_POLL */ #ifdef CONFIG_ELOOP_SELECT fd_set *rfds, *wfds, *efds; struct timeval _tv; #endif /* CONFIG_ELOOP_SELECT */ #ifdef CONFIG_ELOOP_EPOLL int timeout_ms = -1; #endif /* CONFIG_ELOOP_EPOLL */ int res; struct os_reltime tv, now; #ifdef CONFIG_ELOOP_SELECT rfds = os_malloc(sizeof(*rfds)); wfds = os_malloc(sizeof(*wfds)); efds = os_malloc(sizeof(*efds)); if (rfds == NULL || wfds == NULL || efds == NULL) goto out; #endif /* CONFIG_ELOOP_SELECT */ while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) { struct eloop_timeout *timeout; timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_reltime(&now); if (os_reltime_before(&now, &timeout->time)) os_reltime_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) timeout_ms = tv.sec * 1000 + tv.usec / 1000; #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */ #ifdef CONFIG_ELOOP_SELECT _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec; #endif /* CONFIG_ELOOP_SELECT */ } #ifdef CONFIG_ELOOP_POLL num_poll_fds = eloop_sock_table_set_fds( &eloop.readers, &eloop.writers, &eloop.exceptions, eloop.pollfds, eloop.pollfds_map, eloop.max_pollfd_map); res = poll(eloop.pollfds, num_poll_fds, timeout ? timeout_ms : -1); #endif /* CONFIG_ELOOP_POLL */ #ifdef CONFIG_ELOOP_SELECT eloop_sock_table_set_fds(&eloop.readers, rfds); eloop_sock_table_set_fds(&eloop.writers, wfds); eloop_sock_table_set_fds(&eloop.exceptions, efds); res = select(eloop.max_sock + 1, rfds, wfds, efds, timeout ? &_tv : NULL); #endif /* CONFIG_ELOOP_SELECT */ #ifdef CONFIG_ELOOP_EPOLL if (eloop.count == 0) { res = 0; } else { res = epoll_wait(eloop.epollfd, eloop.epoll_events, eloop.count, timeout_ms); } #endif /* CONFIG_ELOOP_EPOLL */ if (res < 0 && errno != EINTR && errno != 0) { wpa_printf(MSG_ERROR, "eloop: %s: %s", #ifdef CONFIG_ELOOP_POLL "poll" #endif /* CONFIG_ELOOP_POLL */ #ifdef CONFIG_ELOOP_SELECT "select" #endif /* CONFIG_ELOOP_SELECT */ #ifdef CONFIG_ELOOP_EPOLL "epoll" #endif /* CONFIG_ELOOP_EPOLL */ , strerror(errno)); goto out; } eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_reltime(&now); if (!os_reltime_before(&now, &timeout->time)) { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; eloop_timeout_handler handler = timeout->handler; eloop_remove_timeout(timeout); handler(eloop_data, user_data); } } if (res <= 0) continue; #ifdef CONFIG_ELOOP_POLL eloop_sock_table_dispatch(&eloop.readers, &eloop.writers, &eloop.exceptions, eloop.pollfds_map, eloop.max_pollfd_map); #endif /* CONFIG_ELOOP_POLL */ #ifdef CONFIG_ELOOP_SELECT eloop_sock_table_dispatch(&eloop.readers, rfds); eloop_sock_table_dispatch(&eloop.writers, wfds); eloop_sock_table_dispatch(&eloop.exceptions, efds); #endif /* CONFIG_ELOOP_SELECT */ #ifdef CONFIG_ELOOP_EPOLL eloop_sock_table_dispatch(eloop.epoll_events, res); #endif /* CONFIG_ELOOP_EPOLL */ } eloop.terminate = 0; out: #ifdef CONFIG_ELOOP_SELECT os_free(rfds); os_free(wfds); os_free(efds); #endif /* CONFIG_ELOOP_SELECT */ return; }
/** * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors * @ifname: Interface name for global control socket or %NULL * @sock: Local socket fd * @ctrl_dst: List of attached listeners * @level: Priority level of the message * @buf: Message data * @len: Message length * * Send a packet to all monitor programs attached to the control interface. */ static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, const char *ifname, int sock, struct dl_list *ctrl_dst, int level, const char *buf, size_t len, struct ctrl_iface_priv *priv, struct ctrl_iface_global_priv *gp) { struct wpa_ctrl_dst *dst, *next; char levelstr[10]; int idx, res; struct msghdr msg; struct iovec io[5]; if (sock < 0 || dl_list_empty(ctrl_dst)) return; res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); if (os_snprintf_error(sizeof(levelstr), res)) return; idx = 0; if (ifname) { io[idx].iov_base = "IFNAME="; io[idx].iov_len = 7; idx++; io[idx].iov_base = (char *) ifname; io[idx].iov_len = os_strlen(ifname); idx++; io[idx].iov_base = " "; io[idx].iov_len = 1; idx++; } io[idx].iov_base = levelstr; io[idx].iov_len = os_strlen(levelstr); idx++; io[idx].iov_base = (char *) buf; io[idx].iov_len = len; idx++; os_memset(&msg, 0, sizeof(msg)); msg.msg_iov = io; msg.msg_iovlen = idx; dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) { int _errno; char txt[200]; if (level < dst->debug_level) continue; msg.msg_name = (void *) &dst->addr; msg.msg_namelen = dst->addrlen; wpas_ctrl_sock_debug("ctrl_sock-sendmsg", sock, buf, len); if (sendmsg(sock, &msg, MSG_DONTWAIT) >= 0) { sockaddr_print(MSG_MSGDUMP, "CTRL_IFACE monitor sent successfully to", &dst->addr, dst->addrlen); dst->errors = 0; continue; } _errno = errno; os_snprintf(txt, sizeof(txt), "CTRL_IFACE monitor: %d (%s) for", _errno, strerror(_errno)); sockaddr_print(MSG_DEBUG, txt, &dst->addr, dst->addrlen); dst->errors++; if (dst->errors > 10 || _errno == ENOENT || _errno == EPERM) { sockaddr_print(MSG_INFO, "CTRL_IFACE: Detach monitor that cannot receive messages:", &dst->addr, dst->addrlen); wpa_supplicant_ctrl_iface_detach(ctrl_dst, &dst->addr, dst->addrlen); } if (_errno == ENOBUFS || _errno == EAGAIN) { /* * The socket send buffer could be full. This may happen * if client programs are not receiving their pending * messages. Close and reopen the socket as a workaround * to avoid getting stuck being unable to send any new * responses. */ if (priv) sock = wpas_ctrl_iface_reinit(wpa_s, priv); else if (gp) sock = wpas_ctrl_iface_global_reinit( wpa_s->global, gp); else break; if (sock < 0) { wpa_dbg(wpa_s, MSG_DEBUG, "Failed to reinitialize ctrl_iface socket"); break; } } }
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) { struct wpa_ctrl_dst *dst, *prev; struct ctrl_iface_msg *msg, *prev_msg; struct ctrl_iface_global_priv *gpriv; if (priv->sock > -1) { char *fname; char *buf, *dir = NULL; eloop_unregister_read_sock(priv->sock); if (!dl_list_empty(&priv->ctrl_dst)) { /* * Wait before closing the control socket if * there are any attached monitors in order to allow * them to receive any pending messages. */ wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " "monitors to receive messages"); os_sleep(0, 100000); } close(priv->sock); priv->sock = -1; fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); if (fname) { unlink(fname); os_free(fname); } if (priv->wpa_s->conf->ctrl_interface == NULL) goto free_dst; buf = os_strdup(priv->wpa_s->conf->ctrl_interface); if (buf == NULL) goto free_dst; if (os_strncmp(buf, "DIR=", 4) == 0) { char *gid_str; dir = buf + 4; gid_str = os_strstr(dir, " GROUP="); if (gid_str) *gid_str = '\0'; } else dir = buf; if (rmdir(dir) < 0) { if (errno == ENOTEMPTY) { wpa_printf(MSG_DEBUG, "Control interface " "directory not empty - leaving it " "behind"); } else { wpa_printf(MSG_ERROR, "rmdir[ctrl_interface=%s]: %s", dir, strerror(errno)); } } os_free(buf); } free_dst: dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst, list) { dl_list_del(&dst->list); os_free(dst); } dl_list_for_each_safe(msg, prev_msg, &priv->msg_queue, struct ctrl_iface_msg, list) { dl_list_del(&msg->list); os_free(msg); } gpriv = priv->wpa_s->global->ctrl_iface; if (gpriv) { dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue, struct ctrl_iface_msg, list) { if (msg->wpa_s == priv->wpa_s) { dl_list_del(&msg->list); os_free(msg); } } } eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL); os_free(priv); }
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, enum wpa_msg_type type, const char *txt, size_t len) { struct wpa_supplicant *wpa_s = ctx; struct ctrl_iface_priv *priv; struct ctrl_iface_global_priv *gpriv; if (wpa_s == NULL) return; gpriv = wpa_s->global->ctrl_iface; if (type != WPA_MSG_NO_GLOBAL && gpriv && !dl_list_empty(&gpriv->ctrl_dst)) { if (!dl_list_empty(&gpriv->msg_queue) || wpas_ctrl_iface_throttle(gpriv->sock)) { if (gpriv->throttle_count == 0) { wpa_printf(MSG_MSGDUMP, "CTRL: Had to throttle global event message for sock %d", gpriv->sock); } gpriv->throttle_count++; wpas_ctrl_msg_queue_limit(gpriv->throttle_count, &gpriv->msg_queue); wpas_ctrl_msg_queue(&gpriv->msg_queue, wpa_s, level, type, txt, len); } else { if (gpriv->throttle_count) { wpa_printf(MSG_MSGDUMP, "CTRL: Had to throttle %u global event message(s) for sock %d", gpriv->throttle_count, gpriv->sock); } gpriv->throttle_count = 0; wpa_supplicant_ctrl_iface_send( wpa_s, type != WPA_MSG_PER_INTERFACE ? NULL : wpa_s->ifname, gpriv->sock, &gpriv->ctrl_dst, level, txt, len, NULL, gpriv); } } priv = wpa_s->ctrl_iface; if (type != WPA_MSG_ONLY_GLOBAL && priv) { if (!dl_list_empty(&priv->msg_queue) || wpas_ctrl_iface_throttle(priv->sock)) { if (priv->throttle_count == 0) { wpa_printf(MSG_MSGDUMP, "CTRL: Had to throttle event message for sock %d", priv->sock); } priv->throttle_count++; wpas_ctrl_msg_queue_limit(priv->throttle_count, &priv->msg_queue); wpas_ctrl_msg_queue(&priv->msg_queue, wpa_s, level, type, txt, len); } else { if (priv->throttle_count) { wpa_printf(MSG_MSGDUMP, "CTRL: Had to throttle %u event message(s) for sock %d", priv->throttle_count, priv->sock); } priv->throttle_count = 0; wpa_supplicant_ctrl_iface_send(wpa_s, NULL, priv->sock, &priv->ctrl_dst, level, txt, len, priv, NULL); } } }
static void rx_data_bss_prot(struct wlantest *wt, const struct ieee80211_hdr *hdr, const u8 *qos, const u8 *dst, const u8 *src, const u8 *data, size_t len) { struct wlantest_bss *bss; struct wlantest_sta *sta, *sta2; int keyid; u16 fc = le_to_host16(hdr->frame_control); u8 *decrypted; size_t dlen; int tid; u8 pn[6], *rsc; struct wlantest_tdls *tdls = NULL, *found; const u8 *tk = NULL; int ptk_iter_done = 0; int try_ptk_iter = 0; if (hdr->addr1[0] & 0x01) { rx_data_bss_prot_group(wt, hdr, qos, dst, src, data, len); return; } if (fc & WLAN_FC_TODS) { bss = bss_get(wt, hdr->addr1); if (bss == NULL) return; sta = sta_get(bss, hdr->addr2); if (sta) sta->counters[WLANTEST_STA_COUNTER_PROT_DATA_TX]++; } else if (fc & WLAN_FC_FROMDS) { bss = bss_get(wt, hdr->addr2); if (bss == NULL) return; sta = sta_get(bss, hdr->addr1); } else { bss = bss_get(wt, hdr->addr3); if (bss == NULL) return; sta = sta_find(bss, hdr->addr2); sta2 = sta_find(bss, hdr->addr1); if (sta == NULL || sta2 == NULL) return; found = NULL; dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) { if ((tdls->init == sta && tdls->resp == sta2) || (tdls->init == sta2 && tdls->resp == sta)) { found = tdls; if (tdls->link_up) break; } } if (found) { if (!found->link_up) add_note(wt, MSG_DEBUG, "TDLS: Link not up, but Data " "frame seen"); tk = found->tpk.tk; tdls = found; } } if ((sta == NULL || (!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) && tk == NULL) { add_note(wt, MSG_MSGDUMP, "No PTK known to decrypt the frame"); if (dl_list_empty(&wt->ptk)) return; try_ptk_iter = 1; } if (len < 4) { add_note(wt, MSG_INFO, "Too short encrypted data frame"); return; } if (sta == NULL) return; if (sta->pairwise_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) && !(data[3] & 0x20)) { add_note(wt, MSG_INFO, "Expected TKIP/CCMP frame from " MACSTR " did not have ExtIV bit set to 1", MAC2STR(src)); return; } if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP) { if (data[3] & 0x1f) { add_note(wt, MSG_INFO, "TKIP frame from " MACSTR " used non-zero reserved bit", MAC2STR(hdr->addr2)); } if (data[1] != ((data[0] | 0x20) & 0x7f)) { add_note(wt, MSG_INFO, "TKIP frame from " MACSTR " used incorrect WEPSeed[1] (was 0x%x, " "expected 0x%x)", MAC2STR(hdr->addr2), data[1], (data[0] | 0x20) & 0x7f); } } else if (tk || sta->pairwise_cipher == WPA_CIPHER_CCMP) { if (data[2] != 0 || (data[3] & 0x1f) != 0) { add_note(wt, MSG_INFO, "CCMP frame from " MACSTR " used non-zero reserved bit", MAC2STR(hdr->addr2)); } } keyid = data[3] >> 6; if (keyid != 0) { add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in " "individually addressed Data frame from " MACSTR, keyid, MAC2STR(hdr->addr2)); } if (qos) { tid = qos[0] & 0x0f; if (fc & WLAN_FC_TODS) sta->tx_tid[tid]++; else sta->rx_tid[tid]++; } else { tid = 0; if (fc & WLAN_FC_TODS) sta->tx_tid[16]++; else sta->rx_tid[16]++; } if (tk) { if (os_memcmp(hdr->addr2, tdls->init->addr, ETH_ALEN) == 0) rsc = tdls->rsc_init[tid]; else rsc = tdls->rsc_resp[tid]; } else if (fc & WLAN_FC_TODS) rsc = sta->rsc_tods[tid]; else rsc = sta->rsc_fromds[tid]; if (tk == NULL && sta->pairwise_cipher == WPA_CIPHER_TKIP) tkip_get_pn(pn, data); else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) goto skip_replay_det; else ccmp_get_pn(pn, data); if (os_memcmp(pn, rsc, 6) <= 0) { u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl)); wpa_hexdump(MSG_INFO, "RX PN", pn, 6); wpa_hexdump(MSG_INFO, "RSC", rsc, 6); } skip_replay_det: if (tk) decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen); else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) decrypted = tkip_decrypt(sta->ptk.tk1, hdr, data, len, &dlen); else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) decrypted = wep_decrypt(wt, hdr, data, len, &dlen); else if (sta->ptk_set) decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len, &dlen); else { decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, len, &dlen); ptk_iter_done = 1; } if (!decrypted && !ptk_iter_done) { decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, len, &dlen); if (decrypted) { add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs"); } } if (decrypted) { u16 fc = le_to_host16(hdr->frame_control); const u8 *peer_addr = NULL; if (!(fc & (WLAN_FC_FROMDS | WLAN_FC_TODS))) peer_addr = hdr->addr1; os_memcpy(rsc, pn, 6); rx_data_process(wt, bss->bssid, sta->addr, dst, src, decrypted, dlen, 1, peer_addr); write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0), decrypted, dlen); } else if (!try_ptk_iter) add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); os_free(decrypted); }
void fst_session_global_deinit(void) { WPA_ASSERT(dl_list_empty(&global_sessions_list)); }
void eloop_run(void) { fd_set *rfds, *wfds, *efds; int res; struct timeval _tv; struct os_time tv, now; rfds = os_malloc(sizeof(*rfds)); wfds = os_malloc(sizeof(*wfds)); efds = os_malloc(sizeof(*efds)); if (rfds == NULL || wfds == NULL || efds == NULL) goto out; while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) { struct eloop_timeout *timeout; timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_time(&now); if (os_time_before(&now, &timeout->time)) os_time_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec; } eloop_sock_table_set_fds(&eloop.readers, rfds); eloop_sock_table_set_fds(&eloop.writers, wfds); eloop_sock_table_set_fds(&eloop.exceptions, efds); res = select(eloop.max_sock + 1, rfds, wfds, efds, timeout ? &_tv : NULL); if (res < 0 && errno != EINTR && errno != 0) { perror("select"); goto out; } eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ if (timeout) { os_get_time(&now); if (!os_time_before(&now, &timeout->time)) { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; eloop_timeout_handler handler = timeout->handler; eloop_remove_timeout(timeout); handler(eloop_data, user_data); } } if (res <= 0) continue; eloop_sock_table_dispatch(&eloop.readers, rfds); eloop_sock_table_dispatch(&eloop.writers, wfds); eloop_sock_table_dispatch(&eloop.exceptions, efds); } out: os_free(rfds); os_free(wfds); os_free(efds); }
/** * upnp_wps_device_send_event - Queue event messages for subscribers * @sm: WPS UPnP state machine from upnp_wps_device_init() * * This function queues the last WLANEvent to be sent for all currently * subscribed UPnP control points. sm->wlanevent must have been set with the * encoded data before calling this function. */ static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm) { /* Enqueue event message for all subscribers */ struct wpabuf *buf; /* holds event message */ int buf_size = 0; struct subscription *s, *tmp; /* Actually, utf-8 is the default, but it doesn't hurt to specify it */ const char *format_head = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n"; const char *format_tail = "</e:propertyset>\n"; struct os_time now; if (dl_list_empty(&sm->subscriptions)) { /* optimize */ return; } if (os_get_time(&now) == 0) { if (now.sec != sm->last_event_sec) { sm->last_event_sec = now.sec; sm->num_events_in_sec = 1; } else { sm->num_events_in_sec++; /* * In theory, this should apply to all WLANEvent * notifications, but EAP messages are of much higher * priority and Probe Request notifications should not * be allowed to drop EAP messages, so only throttle * Probe Request notifications. */ if (sm->num_events_in_sec > MAX_EVENTS_PER_SEC && sm->wlanevent_type == UPNP_WPS_WLANEVENT_TYPE_PROBE) { wpa_printf(MSG_DEBUG, "WPS UPnP: Throttle " "event notifications (%u seen " "during one second)", sm->num_events_in_sec); return; } } } /* Determine buffer size needed first */ buf_size += os_strlen(format_head); buf_size += 50 + 2 * os_strlen("WLANEvent"); if (sm->wlanevent) buf_size += os_strlen(sm->wlanevent); buf_size += os_strlen(format_tail); buf = wpabuf_alloc(buf_size); if (buf == NULL) return; wpabuf_put_str(buf, format_head); wpabuf_put_property(buf, "WLANEvent", sm->wlanevent); wpabuf_put_str(buf, format_tail); wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s", (char *) wpabuf_head(buf)); dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription, list) { event_add(s, buf, sm->wlanevent_type == UPNP_WPS_WLANEVENT_TYPE_PROBE); } wpabuf_free(buf); }