Example #1
0
static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len)
{
	struct ieee80211_hdr *hdr;
	u16 fc, type, stype;
	size_t data_len = len;
	int ver;
	union wpa_event_data event;

	/* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
	 * these to user space */
	if (len < 24) {
		wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)",
			   (unsigned long) len);
		return;
	}

	hdr = (struct ieee80211_hdr *) buf;
	fc = le_to_host16(hdr->frame_control);
	type = WLAN_FC_GET_TYPE(fc);
	stype = WLAN_FC_GET_STYPE(fc);

	if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) {
		wpa_hexdump(MSG_MSGDUMP, "Received management frame",
			    buf, len);
	}

	ver = fc & WLAN_FC_PVER;

	/* protocol version 2 is reserved for indicating ACKed frame (TX
	 * callbacks), and version 1 for indicating failed frame (no ACK, TX
	 * callbacks) */
	if (ver == 1 || ver == 2) {
		handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0);
		return;
	} else if (ver != 0) {
		printf("unknown protocol version %d\n", ver);
		return;
	}

	switch (type) {
	case WLAN_FC_TYPE_MGMT:
		os_memset(&event, 0, sizeof(event));
		event.rx_mgmt.frame = buf;
		event.rx_mgmt.frame_len = data_len;
		wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
		break;
	case WLAN_FC_TYPE_CTRL:
		wpa_printf(MSG_DEBUG, "CTRL");
		break;
	case WLAN_FC_TYPE_DATA:
		wpa_printf(MSG_DEBUG, "DATA");
		handle_data(drv, buf, data_len, stype);
		break;
	default:
		wpa_printf(MSG_DEBUG, "unknown frame type %d", type);
		break;
	}
}
Example #2
0
static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len)
{
    struct ieee80211_hdr *hdr;
    u16 fc, extra_len, type, stype;
    unsigned char *extra = NULL;
    size_t data_len = len;
    int ver;

    /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
     * these to user space */
    if (len < 24) {
        wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)",
                   (unsigned long) len);
        return;
    }

    hdr = (struct ieee80211_hdr *) buf;
    fc = le_to_host16(hdr->frame_control);
    type = WLAN_FC_GET_TYPE(fc);
    stype = WLAN_FC_GET_STYPE(fc);

    if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) {
        wpa_hexdump(MSG_MSGDUMP, "Received management frame",
                    buf, len);
    }

    ver = fc & WLAN_FC_PVER;

    /* protocol version 3 is reserved for indicating extra data after the
     * payload, version 2 for indicating ACKed frame (TX callbacks), and
     * version 1 for indicating failed frame (no ACK, TX callbacks) */
    if (ver == 3) {
        u8 *pos = buf + len - 2;
        extra_len = WPA_GET_LE16(pos);
        printf("extra data in frame (elen=%d)\n", extra_len);
        if ((size_t) extra_len + 2 > len) {
            printf("  extra data overflow\n");
            return;
        }
        len -= extra_len + 2;
        extra = buf + len;
    } else if (ver == 1 || ver == 2) {
        handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0);
        return;
    } else if (ver != 0) {
        printf("unknown protocol version %d\n", ver);
        return;
    }

    switch (type) {
    case WLAN_FC_TYPE_MGMT:
        if (stype != WLAN_FC_STYPE_BEACON)
            wpa_printf(MSG_MSGDUMP, "MGMT");
        ieee802_11_mgmt(hapd, buf, data_len, stype, NULL);
        break;
    case WLAN_FC_TYPE_CTRL:
        wpa_printf(MSG_DEBUG, "CTRL");
        break;
    case WLAN_FC_TYPE_DATA:
        wpa_printf(MSG_DEBUG, "DATA");
        handle_data(hapd, buf, data_len, stype);
        break;
    default:
        wpa_printf(MSG_DEBUG, "unknown frame type %d", type);
        break;
    }
}
Example #3
0
static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
{
	struct wpa_driver_nl80211_data *drv = eloop_ctx;
	int len;
	unsigned char buf[3000];
	struct ieee80211_radiotap_iterator iter;
	int ret;
	int datarate = 0, ssi_signal = 0;
	int injected = 0, failed = 0, rxflags = 0;

	len = recv(sock, buf, sizeof(buf), 0);
	if (len < 0) {
		wpa_printf(MSG_ERROR, "nl80211: Monitor socket recv failed: %s",
			   strerror(errno));
		return;
	}

	if (ieee80211_radiotap_iterator_init(&iter, (void *) buf, len, NULL)) {
		wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame");
		return;
	}

	while (1) {
		ret = ieee80211_radiotap_iterator_next(&iter);
		if (ret == -ENOENT)
			break;
		if (ret) {
			wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame (%d)",
				   ret);
			return;
		}
		switch (iter.this_arg_index) {
		case IEEE80211_RADIOTAP_FLAGS:
			if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
				len -= 4;
			break;
		case IEEE80211_RADIOTAP_RX_FLAGS:
			rxflags = 1;
			break;
		case IEEE80211_RADIOTAP_TX_FLAGS:
			injected = 1;
			failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
					IEEE80211_RADIOTAP_F_TX_FAIL;
			break;
		case IEEE80211_RADIOTAP_DATA_RETRIES:
			break;
		case IEEE80211_RADIOTAP_CHANNEL:
			/* TODO: convert from freq/flags to channel number */
			break;
		case IEEE80211_RADIOTAP_RATE:
			datarate = *iter.this_arg * 5;
			break;
		case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
			ssi_signal = (s8) *iter.this_arg;
			break;
		}
	}

	if (rxflags && injected)
		return;

	if (!injected)
		handle_frame(drv, buf + iter._max_length,
			     len - iter._max_length, datarate, ssi_signal);
	else
		handle_tx_callback(drv->ctx, buf + iter._max_length,
				   len - iter._max_length, !failed);
}
Example #4
0
static void handle_frame(hostapd *hapd, char *buf, size_t len)
{
	struct ieee80211_hdr *hdr;
	u16 fc, extra_len, type, stype;
	unsigned char *extra = NULL;
	size_t data_len = len;
	int ver;

	/* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
	 * these to user space */
	if (len < 24) {
		printf("handle_frame: too short (%d)\n", len);
		return;
	}

	hdr = (struct ieee80211_hdr *) buf;
	fc = le_to_host16(hdr->frame_control);

	ver = fc & WLAN_FC_PVER;

	/* protocol version 3 is reserved for indicating extra data after the
	 * payload, version 2 for indicating ACKed frame (TX callbacks), and
	 * version 1 for indicating failed frame (no ACK, TX callbacks) */
	if (ver == 3) {
		u16 *elen;
		elen = (u16 *) (buf + len - 1);
		extra_len = le_to_host16(*elen);
		printf("extra data in frame (elen=%d)\n", extra_len);
		if (extra_len + 2 > len) {
			printf("  extra data overflow\n");
			return;
		}
		len -= extra_len + 2;
		extra = buf + len;
	} else if (ver == 1 || ver == 2) {
		handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0);
		return;
	} else if (ver != 0) {
		printf("unknown protocol version %d\n", ver);
		return;
	}

	type = WLAN_FC_GET_TYPE(fc);
	stype = WLAN_FC_GET_STYPE(fc);

	switch (type) {
	case WLAN_FC_TYPE_MGMT:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "MGMT\n");
		ieee802_11_mgmt(hapd, buf, data_len, stype);
		break;
	case WLAN_FC_TYPE_CTRL:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "CTRL\n");
		break;
	case WLAN_FC_TYPE_DATA:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "DATA\n");
		handle_data(hapd, buf, data_len, stype);
		break;
	default:
		printf("unknown frame type %d\n", type);
		break;
	}
}
Example #5
0
static void handle_frame(hostapd *hapd, char *buf, size_t len)
{
	struct ieee80211_hdr *hdr;
	u16 fc, extra_len, type, stype;
	unsigned char *extra = NULL;
	size_t data_len = len;
	int ver;

	/* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
	 * these to user space */
	if (len < 24) {
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "handle_frame: too short "
			      "(%d)\n", len);
		return;
	}

	hdr = (struct ieee80211_hdr *) buf;
	fc = le_to_host16(hdr->frame_control);
	type = WLAN_FC_GET_TYPE(fc);
	stype = WLAN_FC_GET_STYPE(fc);

	if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON ||
	    hapd->conf->debug >= HOSTAPD_DEBUG_EXCESSIVE) {
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE,
			      "Received %d bytes management frame\n", len);
		if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) {
			hostapd_hexdump("RX frame", buf, len);
		}
	}

	ver = fc & WLAN_FC_PVER;

	/* protocol version 3 is reserved for indicating extra data after the
	 * payload, version 2 for indicating ACKed frame (TX callbacks), and
	 * version 1 for indicating failed frame (no ACK, TX callbacks) */
	if (ver == 3) {
		u8 *pos = buf + len - 2;
		extra_len = (u16) pos[1] << 8 | pos[0];
		printf("extra data in frame (elen=%d)\n", extra_len);
		if (extra_len + 2 > len) {
			printf("  extra data overflow\n");
			return;
		}
		len -= extra_len + 2;
		extra = buf + len;
	} else if (ver == 1 || ver == 2) {
		handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0);
		return;
	} else if (ver != 0) {
		printf("unknown protocol version %d\n", ver);
		return;
	}

	switch (type) {
	case WLAN_FC_TYPE_MGMT:
		HOSTAPD_DEBUG(stype == WLAN_FC_STYPE_BEACON ?
			      HOSTAPD_DEBUG_EXCESSIVE : HOSTAPD_DEBUG_VERBOSE,
			      "MGMT\n");
		ieee802_11_mgmt(hapd, buf, data_len, stype);
		break;
	case WLAN_FC_TYPE_CTRL:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "CTRL\n");
		break;
	case WLAN_FC_TYPE_DATA:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "DATA\n");
		handle_data(hapd, buf, data_len, stype);
		break;
	default:
		printf("unknown frame type %d\n", type);
		break;
	}
}