Beispiel #1
0
void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
                        u16 stype, int ok)
{
    struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;

    switch (stype) {
    case WLAN_FC_STYPE_AUTH:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::auth cb\n");
        handle_auth_cb(hapd, mgmt, len, ok);
        break;
    case WLAN_FC_STYPE_ASSOC_RESP:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                      "mgmt::assoc_resp cb\n");
        handle_assoc_cb(hapd, mgmt, len, 0, ok);
        break;
    case WLAN_FC_STYPE_REASSOC_RESP:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                      "mgmt::reassoc_resp cb\n");
        handle_assoc_cb(hapd, mgmt, len, 1, ok);
        break;
    default:
        printf("unknown mgmt cb frame subtype %d\n", stype);
        break;
    }
}
Beispiel #2
0
static void handle_tx_callback(hostapd *hapd, char *buf, size_t len, int ok)
{
	struct ieee80211_hdr *hdr;
	u16 fc, type, stype;
	hdr = (struct ieee80211_hdr *) buf;
	fc = le_to_host16(hdr->frame_control);

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

	switch (type) {
	case WLAN_FC_TYPE_MGMT:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "MGMT (TX callback) %s\n", ok ? "ACK" : "fail");
		ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
		break;
	case WLAN_FC_TYPE_CTRL:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "CTRL (TX callback) %s\n", ok ? "ACK" : "fail");
		break;
	case WLAN_FC_TYPE_DATA:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "DATA (TX callback) %s\n", ok ? "ACK" : "fail");
		/* TODO: could replace TXExc counter hack with kernel driver
		 * in data polling for inactivity check with the new TX
		 * callback.. */
		/* handle_data_cb(hapd, buf, len, stype, ok); */
		break;
	default:
		printf("unknown TX callback frame type %d\n", type);
		break;
	}
}
Beispiel #3
0
static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
				const u8 *buf, size_t len)
{
	struct rsn_preauth_interface *piface = ctx;
	struct hostapd_data *hapd = piface->hapd;
	struct ieee802_1x_hdr *hdr;
	struct sta_info *sta;
	struct l2_ethhdr *ethhdr;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: receive pre-auth packet "
		      "from interface '%s'\n", piface->ifname);
	if (len < sizeof(*ethhdr) + sizeof(*hdr)) {
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: too short pre-auth "
			      "packet (len=%lu)\n", (unsigned long) len);
		return;
	}

	ethhdr = (struct l2_ethhdr *) buf;
	hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);

	if (memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for "
			      "foreign address " MACSTR "\n",
			      MAC2STR(ethhdr->h_dest));
		return;
	}

	sta = ap_get_sta(hapd, ethhdr->h_source);
	if (sta && (sta->flags & WLAN_STA_ASSOC)) {
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for "
			      "already association STA " MACSTR "\n",
			      MAC2STR(sta->addr));
		return;
	}
	if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
		sta = ap_sta_add(hapd, ethhdr->h_source);
		if (sta == NULL)
			return;
		sta->flags = WLAN_STA_PREAUTH;

		ieee802_1x_new_station(hapd, sta);
		if (sta->eapol_sm == NULL) {
			ap_free_sta(hapd, sta);
			sta = NULL;
		} else {
			sta->eapol_sm->radius_identifier = -1;
			sta->eapol_sm->portValid = TRUE;
			sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
		}
	}
	if (sta == NULL)
		return;
	sta->preauth_iface = piface;
	ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
			   len - sizeof(*ethhdr));
}
Beispiel #4
0
/* This function will be called whenever a station associates with the AP */
void hostapd_new_assoc_sta(hostapd *hapd, struct sta_info *sta)
{

	if (hapd->tkip_countermeasures) {
		hostapd_sta_deauth(hapd, sta->addr, 
				     WLAN_REASON_MICHAEL_MIC_FAILURE);
		return;
	}
	
	/* IEEE 802.11F (IAPP) */
	if (hapd->conf->ieee802_11f)
		iapp_new_station(hapd->iapp, sta);

	/* Start accounting here, if IEEE 802.1X is not used. IEEE 802.1X code
	 * will start accounting after the station has been authorized. */
	if (!hapd->conf->ieee802_1x)
		accounting_sta_start(hapd, sta);

#ifdef JUMPSTART
	if (hapd->conf->js_p1) {
		/* Only one STA at a time to attempt Jumpstart */
		if (!hapd->jsw_profile->p1_in_progress) {
			hapd->jsw_profile->p1_in_progress = 1;
			HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, 
				      "JUMPSTART: " MACSTR 
				      " %s: starting P1\n",
				       MAC2STR(sta->addr), __func__); 
			js_p1_new_station(hapd, sta);
			/* Start the JS state machine */
			smSendEvent(sta->js_session, JSW_EVENT_ASSOC);
			
		} else {
			HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, 
				      "JUMPSTART: " MACSTR
				      "%s: P1 running with another STA."
				      " Disassoc\n",
				       MAC2STR(sta->addr), __func__); 
			hostapd_sta_disassoc(hapd, sta->addr, 
					     WLAN_REASON_UNSPECIFIED);
		}	
		return;
	}
#endif /* JUMPSTART */

	/* Start IEEE 802.1x authentication process for new stations */
	ieee802_1x_new_station(hapd, sta);
	wpa_new_station(hapd, sta);
}
Beispiel #5
0
u8 radius_client_get_id(struct radius_client_data *radius)
{
    struct hostapd_data *hapd = radius->hapd;
    struct radius_msg_list *entry, *prev, *remove;
    u8 id = radius->next_radius_identifier++;

    /* remove entries with matching id from retransmit list to avoid
     * using new reply from the RADIUS server with an old request */
    entry = radius->msgs;
    prev = NULL;
    while (entry) {
        if (entry->msg->hdr->identifier == id) {
            HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                          "Removing pending RADIUS message, since "
                          "its id (%d) is reused\n", id);
            if (prev)
                prev->next = entry->next;
            else
                radius->msgs = entry->next;
            remove = entry;
        } else
            remove = NULL;
        prev = entry;
        entry = entry->next;

        if (remove)
            radius_client_msg_free(remove);
    }

    return id;
}
Beispiel #6
0
static void radius_client_list_del(struct radius_client_data *radius,
                                   RadiusType msg_type, u8 *addr)
{
    struct hostapd_data *hapd = radius->hapd;
    struct radius_msg_list *entry, *prev, *tmp;

    if (addr == NULL)
        return;

    entry = radius->msgs;
    prev = NULL;
    while (entry) {
        if (entry->msg_type == msg_type &&
                memcmp(entry->addr, addr, ETH_ALEN) == 0) {
            if (prev)
                prev->next = entry->next;
            else
                radius->msgs = entry->next;
            tmp = entry;
            entry = entry->next;
            HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                          "Removing matching RADIUS message for "
                          MACSTR "\n", MAC2STR(addr));
            radius_client_msg_free(tmp);
            radius->num_msgs--;
            continue;
        }
        prev = entry;
        entry = entry->next;
    }
}
Beispiel #7
0
static void radius_client_update_timeout(struct radius_client_data *radius)
{
    struct hostapd_data *hapd = radius->hapd;
    time_t now, first;
    struct radius_msg_list *entry;

    eloop_cancel_timeout(radius_client_timer, radius, NULL);

    if (radius->msgs == NULL) {
        return;
    }

    first = 0;
    for (entry = radius->msgs; entry; entry = entry->next) {
        if (first == 0 || entry->next_try < first)
            first = entry->next_try;
    }

    time(&now);
    if (first < now)
        first = now;
    eloop_register_timeout(first - now, 0, radius_client_timer, radius,
                           NULL);
    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Next RADIUS client retransmit in"
                  " %ld seconds\n", (long int) (first - now));
}
Beispiel #8
0
void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
		      u8 *buf, size_t len)
{
	struct rsn_preauth_interface *piface;
	struct l2_ethhdr *ethhdr;

	piface = hapd->preauth_iface;
	while (piface) {
		if (piface == sta->preauth_iface)
			break;
		piface = piface->next;
	}

	if (piface == NULL) {
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: Could not find "
			      "pre-authentication interface for " MACSTR "\n",
			      MAC2STR(sta->addr));
		return;
	}

	ethhdr = malloc(sizeof(*ethhdr) + len);
	if (ethhdr == NULL)
		return;

	memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
	memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
	ethhdr->h_proto = htons(ETH_P_PREAUTH);
	memcpy(ethhdr + 1, buf, len);

	if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
			   sizeof(*ethhdr) + len) < 0) {
		printf("Failed to send preauth packet using l2_packet_send\n");
	}
	free(ethhdr);
}
Beispiel #9
0
static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
{
	struct rsn_preauth_interface *piface;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN pre-auth interface '%s'\n",
		      ifname);

	piface = wpa_zalloc(sizeof(*piface));
	if (piface == NULL)
		return -1;
	piface->hapd = hapd;

	piface->ifname = strdup(ifname);
	if (piface->ifname == NULL) {
		goto fail1;
	}

	piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
				    rsn_preauth_receive, piface, 1);
	if (piface->l2 == NULL) {
		printf("Failed to open register layer 2 access to "
		       "ETH_P_PREAUTH\n");
		goto fail2;
	}

	piface->next = hapd->preauth_iface;
	hapd->preauth_iface = piface;
	return 0;

fail2:
	free(piface->ifname);
fail1:
	free(piface);
	return -1;
}
static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
{
	struct hostapd_acl_query_data *prev, *entry, *tmp;

	prev = NULL;
	entry = hapd->acl_queries;

	while (entry) {
		if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
			HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
				      "ACL query for " MACSTR
				      " has expired.\n", MAC2STR(entry->addr));
			if (prev)
				prev->next = entry->next;
			else
				hapd->acl_queries = entry->next;

			tmp = entry;
			entry = entry->next;
			hostapd_acl_query_free(tmp);
			continue;
		}

		prev = entry;
		entry = entry->next;
	}
}
static int radius_client_retransmit(hostapd *hapd,
				    struct radius_msg_list *entry, time_t now)
{
	int s;

	if (entry->msg_type == RADIUS_ACCT)
		s = hapd->radius->acct_serv_sock;
	else
		s = hapd->radius->auth_serv_sock;

	/* retransmit; remove entry if too many attempts */
	entry->attempts++;
	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Resending RADIUS message (id=%d)"
		      "\n", entry->msg->hdr->identifier);

	if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
		perror("send[RADIUS]");

	entry->next_try = now + entry->next_wait;
	entry->next_wait *= 2;
	if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
		entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
	if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
		printf("Removing un-ACKed RADIUS message due to too many "
		       "failed retransmit attempts\n");
		return 1;
	}

	return 0;
}
Beispiel #12
0
static void hostapd_acl_expire_cache(hostapd *hapd, time_t now)
{
	struct hostapd_cached_radius_acl *prev, *entry, *tmp;

	prev = NULL;
	entry = hapd->acl_cache;

	while (entry) {
		if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
			HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
				      "Cached ACL entry for " MACSTR
				      " has expired.\n", MAC2STR(entry->addr));
			if (prev)
				prev->next = entry->next;
			else
				hapd->acl_cache = entry->next;

			tmp = entry;
			entry = entry->next;
			free(tmp);
			continue;
		}

		prev = entry;
		entry = entry->next;
	}
}
/**
 * reload_hw_mode_done - Callback for after the HW mode is setup
 * @hapd_iface: Pointer to interface data.
 * @status: Status of the HW mode setup.
 */
static void reload_hw_mode_done(struct hostapd_iface *hapd_iface, int status)
{
	struct hostapd_data *hapd = hapd_iface->bss[0];
	struct hostapd_config_change *change = hapd_iface->change;
	struct hostapd_config *newconf = change->newconf;
	hostapd_iface_cb cb;
	int freq;

	if (status) {
		printf("Failed to select hw_mode.\n");

		cb = hapd_iface->reload_iface_cb;
		hapd_iface->reload_iface_cb = NULL;
		cb(hapd_iface, -1);

		return;
	}

	freq = hostapd_hw_get_freq(hapd, newconf->channel);
	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		      "Mode: %s  Channel: %d  Frequency: %d MHz\n",
		      hostapd_hw_mode_txt(newconf->hw_mode),
		      newconf->channel, freq);

	if (hostapd_set_freq(hapd, newconf->hw_mode, freq)) {
		printf("Could not set channel %d (%d MHz) for kernel "
		       "driver\n", newconf->channel, freq);
	}

	change->beacon_changed++;

	reload_iface2(hapd_iface);
}
Beispiel #14
0
struct sta_info * ap_sta_add(struct hostapd_data *hapd, u8 *addr)
{
    struct sta_info *sta;

    sta = ap_get_sta(hapd, addr);
    if (sta)
        return sta;

    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "  New STA\n");
    if (hapd->num_sta >= MAX_STA_COUNT) {
        /* FIX: might try to remove some old STAs first? */
        printf("  no more room for new STAs (%d/%d)\n",
               hapd->num_sta, MAX_STA_COUNT);
        return NULL;
    }

    sta = (struct sta_info *) malloc(sizeof(struct sta_info));
    if (sta == NULL) {
        printf("  malloc failed\n");
        return NULL;
    }
    memset(sta, 0, sizeof(struct sta_info));
    sta->acct_interim_interval = hapd->conf->radius_acct_interim_interval;

    /* initialize STA info data */
    eloop_register_timeout(AP_MAX_INACTIVITY, 0, ap_handle_timer,
                           hapd, sta);
    memcpy(sta->addr, addr, ETH_ALEN);
    sta->next = hapd->sta_list;
    hapd->sta_list = sta;
    hapd->num_sta++;
    ap_sta_hash_add(hapd, sta);

    return sta;
}
Beispiel #15
0
static int
bsd_set_ieee8021x(void *priv, int enabled)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;
	struct hostapd_config *conf = hapd->conf;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE,
		"%s: enabled=%d\n", __func__, enabled);

	if (!enabled) {
		/* XXX restore state */
		return set80211param(priv, IEEE80211_IOC_AUTHMODE,
			IEEE80211_AUTH_AUTO);
	}
	if (!conf->wpa && !conf->ieee802_1x) {
		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
			HOSTAPD_LEVEL_WARNING, "No 802.1x or WPA enabled!");
		return -1;
	}
	if (conf->wpa && bsd_configure_wpa(drv) != 0) {
		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
			HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
		return -1;
	}
	if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
		(conf->wpa ?  IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
			HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1x!");
		return -1;
	}
	return bsd_set_iface_flags(priv, 1);
}
Beispiel #16
0
static int
bsd_get_seqnum(void *priv, u8 *addr, int idx, u8 *seq)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;
	struct ieee80211req_key wk;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		"%s: addr=%s idx=%d\n", __func__, ether_sprintf(addr), idx);

	memset(&wk, 0, sizeof(wk));
	if (addr == NULL)
		memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
	else
		memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
	wk.ik_keyix = idx;

	if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
		printf("Failed to get encryption.\n");
		return -1;
	} else {
		memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
		return 0;
	}
}
Beispiel #17
0
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
{
	struct sta_info *sta;

	sta = ap_get_sta(hapd, addr);
	if (sta)
		return sta;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "  New STA\n");
	if (hapd->num_sta >= hapd->conf->max_num_sta) {
		/* FIX: might try to remove some old STAs first? */
		printf("  no more room for new STAs (%d/%d)\n",
		       hapd->num_sta, hapd->conf->max_num_sta);
		return NULL;
	}

	sta = wpa_zalloc(sizeof(struct sta_info));
	if (sta == NULL) {
		printf("  malloc failed\n");
		return NULL;
	}
	sta->acct_interim_interval = hapd->conf->radius->acct_interim_interval;

	/* initialize STA info data */
	eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
			       ap_handle_timer, hapd, sta);
	memcpy(sta->addr, addr, ETH_ALEN);
	sta->next = hapd->sta_list;
	hapd->sta_list = sta;
	hapd->num_sta++;
	ap_sta_hash_add(hapd, sta);
	sta->ssid = &hapd->conf->ssid;

	return sta;
}
Beispiel #18
0
void ieee80211_michael_mic_failure(struct hostapd_data *hapd, u8 *addr,
                                   int local)
{
    time_t now;

    if (addr && local) {
        struct sta_info *sta = ap_get_sta(hapd, addr);
        if (sta != NULL) {
            sta->dot11RSNAStatsTKIPLocalMICFailures++;
            hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
                           HOSTAPD_LEVEL_INFO,
                           "Michael MIC failure detected in "
                           "received frame");
        } else {
            HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                          "MLME-MICHAELMICFAILURE.indication "
                          "for not associated STA (" MACSTR
                          ") ignored\n", MAC2STR(addr));
            return;
        }
    }

    time(&now);
    if (now > hapd->michael_mic_failure + 60) {
        hapd->michael_mic_failures = 1;
    } else {
        hapd->michael_mic_failures++;
        if (hapd->michael_mic_failures > 1)
            ieee80211_tkip_countermeasures_start(hapd);
    }
    hapd->michael_mic_failure = now;
}
Beispiel #19
0
void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype)
{
    struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;

    if (stype == WLAN_FC_STYPE_BEACON) {
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, "mgmt::beacon\n");
        handle_beacon(hapd, mgmt, len);
        return;
    }

    if (memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0 &&
            (hapd->assoc_ap_state == DO_NOT_ASSOC ||
             memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0)) {
        printf("MGMT: BSSID=" MACSTR " not our address\n",
               MAC2STR(mgmt->bssid));
        return;
    }


    if (stype == WLAN_FC_STYPE_PROBE_REQ) {
        printf("mgmt::probe_req\n");
        return;
    }

    if (memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
        printf("MGMT: DA=" MACSTR " not our address\n",
               MAC2STR(mgmt->da));
        return;
    }

    switch (stype) {
    case WLAN_FC_STYPE_AUTH:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::auth\n");
        handle_auth(hapd, mgmt, len);
        break;
    case WLAN_FC_STYPE_ASSOC_REQ:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::assoc_req\n");
        handle_assoc(hapd, mgmt, len, 0);
        break;
    case WLAN_FC_STYPE_ASSOC_RESP:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::assoc_resp\n");
        handle_assoc_resp(hapd, mgmt, len);
        break;
    case WLAN_FC_STYPE_REASSOC_REQ:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::reassoc_req\n");
        handle_assoc(hapd, mgmt, len, 1);
        break;
    case WLAN_FC_STYPE_DISASSOC:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::disassoc\n");
        handle_disassoc(hapd, mgmt, len);
        break;
    case WLAN_FC_STYPE_DEAUTH:
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::deauth\n");
        handle_deauth(hapd, mgmt, len);
        break;
    default:
        printf("unknown mgmt frame subtype %d\n", stype);
        break;
    }
}
Beispiel #20
0
int hostapd_init_sockets(struct hostap_driver_data *drv)
{
	struct hostapd_data *hapd = drv->hapd;
	struct ifreq ifr;
	struct sockaddr_ll addr;

	drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (drv->sock < 0) {
		perror("socket[PF_PACKET,SOCK_RAW]");
		return -1;
	}

	if (eloop_register_read_sock(drv->sock, handle_read, drv->hapd, NULL))
	{
		printf("Could not register read socket\n");
		return -1;
	}

        memset(&ifr, 0, sizeof(ifr));
        snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
        if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
		perror("ioctl(SIOCGIFINDEX)");
		return -1;
        }

	if (hostapd_set_iface_flags(drv, 1)) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sll_family = AF_PACKET;
	addr.sll_ifindex = ifr.ifr_ifindex;
	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		      "Opening raw packet socket for ifindex %d\n",
		      addr.sll_ifindex);

	if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
		perror("bind");
		return -1;
	}

        memset(&ifr, 0, sizeof(ifr));
        snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", drv->iface);
        if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
		perror("ioctl(SIOCGIFHWADDR)");
		return -1;
        }

	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
		printf("Invalid HW-addr family 0x%04x\n",
		       ifr.ifr_hwaddr.sa_family);
		return -1;
	}
	memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);

	return 0;
}
Beispiel #21
0
static void handle_disassoc(hostapd *hapd, struct ieee80211_mgmt *mgmt,
                            size_t len)
{
    struct sta_info *sta;

    if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
        printf("handle_disassoc - too short payload (len=%lu)\n",
               (unsigned long) len);
        return;
    }

    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                  "disassocation: STA=" MACSTR " reason_code=%d\n",
                  MAC2STR(mgmt->sa),
                  le_to_host16(mgmt->u.disassoc.reason_code));

    if (hapd->assoc_ap_state != DO_NOT_ASSOC &&
            memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
        printf("Assoc AP " MACSTR " sent disassociation "
               "(reason_code=%d) - try to authenticate\n",
               MAC2STR(hapd->conf->assoc_ap_addr),
               le_to_host16(mgmt->u.disassoc.reason_code));
        hapd->assoc_ap_state = AUTHENTICATE;
        ieee802_11_sta_authenticate(hapd, NULL);
        eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate,
                               hapd, NULL);
        return;
    }

    sta = ap_get_sta(hapd, mgmt->sa);
    if (sta == NULL) {
        printf("Station " MACSTR " trying to disassociate, but it "
               "is not associated.\n", MAC2STR(mgmt->sa));
        return;
    }

    sta->flags &= ~WLAN_STA_ASSOC;
    wpa_sm_event(hapd, sta, WPA_DISASSOC);
    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_INFO, "disassociated");
    sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
    ieee802_1x_set_port_enabled(hapd, sta, 0);
    /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
     * authenticated. */
    accounting_sta_stop(hapd, sta);
    ieee802_1x_free_station(sta);
    hostapd_sta_remove(hapd, sta->addr);

    if (sta->timeout_next == STA_NULLFUNC ||
            sta->timeout_next == STA_DISASSOC) {
        sta->timeout_next = STA_DEAUTH;
        eloop_cancel_timeout(ap_handle_timer, hapd, sta);
        eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
                               hapd, sta);
    }
}
Beispiel #22
0
static void handle_tx_callback(hostapd *hapd, char *buf, size_t len, int ok)
{
	struct ieee80211_hdr *hdr;
	u16 fc, type, stype;
	struct sta_info *sta;

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

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

	switch (type) {
	case WLAN_FC_TYPE_MGMT:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "MGMT (TX callback) %s\n", ok ? "ACK" : "fail");
		ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
		break;
	case WLAN_FC_TYPE_CTRL:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "CTRL (TX callback) %s\n", ok ? "ACK" : "fail");
		break;
	case WLAN_FC_TYPE_DATA:
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "DATA (TX callback) %s\n", ok ? "ACK" : "fail");
		sta = ap_get_sta(hapd, hdr->addr1);
		if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
			HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "STA " MACSTR
				      " %s pending activity poll\n",
				      MAC2STR(sta->addr),
				      ok ? "ACKed" : "did not ACK");
			if (ok)
				sta->flags &= ~WLAN_STA_PENDING_POLL;
		}
		if (sta)
			ieee802_1x_tx_status(hapd, sta, buf, len, ok);
		break;
	default:
		printf("unknown TX callback frame type %d\n", type);
		break;
	}
}
Beispiel #23
0
static int
bsd_set_ssid(void *priv, u8 *buf, int len)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: ssid=\"%.*s\"\n",
		__func__, len, buf);

	return set80211var(priv, IEEE80211_IOC_SSID, buf, len);
}
Beispiel #24
0
static int
bsd_set_privacy(void *priv, int enabled)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		"%s: enabled=%d\n", __func__, enabled);

	return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled);
}
Beispiel #25
0
static int
bsd_set_key(void *priv, const char *alg,
	     unsigned char *addr, int key_idx,
	     u8 *key, size_t key_len)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;
	struct ieee80211req_key wk;
	u_int8_t cipher;

	if (strcmp(alg, "none") == 0)
		return bsd_del_key(priv, addr, key_idx);

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		"%s: alg=%s addr=%s key_idx=%d\n",
		__func__, alg, ether_sprintf(addr), key_idx);

	if (strcmp(alg, "WEP") == 0)
		cipher = IEEE80211_CIPHER_WEP;
	else if (strcmp(alg, "TKIP") == 0)
		cipher = IEEE80211_CIPHER_TKIP;
	else if (strcmp(alg, "CCMP") == 0)
		cipher = IEEE80211_CIPHER_AES_CCM;
	else {
		printf("%s: unknown/unsupported algorithm %s\n",
			__func__, alg);
		return -1;
	}

	if (key_len > sizeof(wk.ik_keydata)) {
		printf("%s: key length %d too big\n", __func__, key_len);
		return -3;
	}

	memset(&wk, 0, sizeof(wk));
	wk.ik_type = cipher;
	wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
	if (addr == NULL) {
		memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
		wk.ik_keyix = key_idx;
		wk.ik_flags |= IEEE80211_KEY_DEFAULT;
	} else {
		memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
		wk.ik_keyix = IEEE80211_KEYIX_NONE;
	}
	wk.ik_keylen = key_len;
	memcpy(wk.ik_keydata, key, key_len);

	return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
}
Beispiel #26
0
static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
{
	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Removing STA " MACSTR
		      " from kernel driver\n", MAC2STR(sta->addr));
	if (hostapd_sta_remove(hapd, sta->addr) &&
	    sta->flags & WLAN_STA_ASSOC) {
		printf("Could not remove station " MACSTR " from kernel "
		       "driver.\n", MAC2STR(sta->addr));
		return -1;
	}
	return 0;
}
Beispiel #27
0
static int
bsd_sta_disassoc(void *priv, u8 *addr, int reason_code)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;
	struct ieee80211req_mlme mlme;

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		"%s: addr=%s reason_code=%d\n",
		__func__, ether_sprintf(addr), reason_code);

	mlme.im_reason = reason_code;
	memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
	return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
}
Beispiel #28
0
static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
{
	struct hostapd_iface *iface = eloop_ctx;
	time_t now;
	struct ap_info *ap;

	eloop_register_timeout(10, 0, ap_list_timer, iface, NULL);

	if (!iface->ap_list)
		return;

	time(&now);

	/* FIX: it looks like jkm-Purina ended up in busy loop in this
	 * function. Apparently, something can still cause a loop in the AP
	 * list.. */

	while (iface->ap_list) {
		ap = iface->ap_list->prev;
		if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
		    now)
			break;

		if (iface->conf->passive_scan_interval > 0)
			ap_list_expired_ap(iface, ap);
		ap_free_ap(iface, ap);
	}

	if (iface->olbc) {
		int olbc = 0;
		ap = iface->ap_list;
		while (ap) {
			if (ap_list_beacon_olbc(iface, ap)) {
				olbc = 1;
				break;
			}
			ap = ap->next;
		}
		if (!olbc) {
			struct hostapd_data *hapd = iface->bss[0];
			HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
				      "OLBC not detected anymore\n");
			iface->olbc = 0;
			ieee802_11_set_beacons(hapd->iface);
		}
	}
}
Beispiel #29
0
static int radius_client_retransmit(struct radius_client_data *radius,
                                    struct radius_msg_list *entry, time_t now)
{
    struct hostapd_data *hapd = radius->hapd;
    int s;

    if (entry->msg_type == RADIUS_ACCT ||
            entry->msg_type == RADIUS_ACCT_INTERIM) {
        s = radius->acct_serv_sock;
        if (entry->attempts == 0)
            hapd->conf->acct_server->requests++;
        else {
            hapd->conf->acct_server->timeouts++;
            hapd->conf->acct_server->retransmissions++;
        }
    } else {
        s = radius->auth_serv_sock;
        if (entry->attempts == 0)
            hapd->conf->auth_server->requests++;
        else {
            hapd->conf->auth_server->timeouts++;
            hapd->conf->auth_server->retransmissions++;
        }
    }

    /* retransmit; remove entry if too many attempts */
    entry->attempts++;
    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Resending RADIUS message (id=%d)"
                  "\n", entry->msg->hdr->identifier);

    gettimeofday(&entry->last_attempt, NULL);
    if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
        radius_client_handle_send_error(radius, s, entry->msg_type);

    entry->next_try = now + entry->next_wait;
    entry->next_wait *= 2;
    if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT)
        entry->next_wait = RADIUS_CLIENT_MAX_WAIT;
    if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) {
        printf("Removing un-ACKed RADIUS message due to too many "
               "failed retransmit attempts\n");
        return 1;
    }

    return 0;
}
Beispiel #30
0
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
			   u16 reason)
{
	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: deauthenticate STA " MACSTR
		      "\n", hapd->conf->iface, MAC2STR(sta->addr));
	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
	if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC))
		ap_sta_remove(hapd, sta);
	sta->timeout_next = STA_REMOVE;
	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
			       ap_handle_timer, hapd, sta);
	accounting_sta_stop(hapd, sta);
	ieee802_1x_free_station(sta);

	mlme_deauthenticate_indication(hapd, sta, reason);
}