Esempio n. 1
0
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);
	}
}
Esempio n. 2
0
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;
	}
}
Esempio n. 4
0
/**
 * 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);
	}
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/* 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);
	}
}
Esempio n. 8
0
File: bss.c Progetto: 2asoft/freebsd
/**
 * 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);
	}
}
Esempio n. 10
0
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);
}
Esempio n. 11
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;
}
Esempio n. 12
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;
}
Esempio n. 13
0
/**
 * 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;
			}
		}
	}
Esempio n. 14
0
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);
}
Esempio n. 15
0
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);
		}
	}
}
Esempio n. 16
0
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);
}
Esempio n. 17
0
void fst_session_global_deinit(void)
{
	WPA_ASSERT(dl_list_empty(&global_sessions_list));
}
Esempio n. 18
0
File: eloop.c Progetto: AxelLin/Drv
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);
}
Esempio n. 19
0
/**
 * 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);
}