Beispiel #1
0
static int hostapd_setup_encryption(hostapd *hapd)
{
	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL))
		hostapd_hexdump("Default WEP key", hapd->default_wep_key,
				hapd->conf->default_wep_key_len);

	hostapd_set_encryption(hapd->driver.data, "none", NULL, 0, NULL, 0);

	if (hostapd_set_encryption(hapd->driver.data, "WEP", NULL,
				   hapd->default_wep_key_idx,
				   hapd->default_wep_key,
				   hapd->conf->default_wep_key_len)) {
		printf("Could not set WEP encryption.\n");
		return -1;
	}

	/* Setup rekeying timer. */
	if (hapd->conf->wep_rekeying_period > 0 &&
	    (hapd->default_wep_key || hapd->conf->individual_wep_key_len > 0)
	    && eloop_register_timeout(hapd->conf->wep_rekeying_period, 0,
				      hostapd_rotate_wep, hapd, NULL)) {
		printf("Couldn't set rekeying timer.\n");
		return -1;
	}

	return 0;
}
Beispiel #2
0
int radius_client_send(struct radius_client_data *radius,
                       struct radius_msg *msg, RadiusType msg_type, u8 *addr)
{
    struct hostapd_data *hapd = radius->hapd;
    u8 *shared_secret;
    size_t shared_secret_len;
    char *name;
    int s, res;

    if (msg_type == RADIUS_ACCT_INTERIM) {
        /* Remove any pending interim acct update for the same STA. */
        radius_client_list_del(radius, msg_type, addr);
    }

    if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
        shared_secret = hapd->conf->acct_server->shared_secret;
        shared_secret_len = hapd->conf->acct_server->shared_secret_len;
        radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
        name = "accounting";
        s = radius->acct_serv_sock;
        hapd->conf->acct_server->requests++;
    } else {
        shared_secret = hapd->conf->auth_server->shared_secret;
        shared_secret_len = hapd->conf->auth_server->shared_secret_len;
        radius_msg_finish(msg, shared_secret, shared_secret_len);
        name = "authentication";
        s = radius->auth_serv_sock;
        hapd->conf->auth_server->requests++;
    }

    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                  "Sending RADIUS message to %s server\n", name);
    if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
        radius_msg_dump(msg);

    res = send(s, msg->buf, msg->buf_used, 0);
    if (res < 0)
        radius_client_handle_send_error(radius, s, msg_type);

    radius_client_list_add(radius, msg, msg_type, shared_secret,
                           shared_secret_len, addr);

    return res;
}
Beispiel #3
0
static int
bsd_send_eapol(void *priv, u8 *addr, u8 *data, size_t data_len, int encrypt)
{
	struct bsd_driver_data *drv = priv;
	hostapd *hapd = drv->hapd;
	unsigned char buf[3000];
	unsigned char *bp = buf;
	struct l2_ethhdr *eth;
	size_t len;
	int status;

	/*
	 * Prepend the Etherent header.  If the caller left us
	 * space at the front we could just insert it but since
	 * we don't know we copy to a local buffer.  Given the frequency
	 * and size of frames this probably doesn't matter.
	 */
	len = data_len + sizeof(struct l2_ethhdr);
	if (len > sizeof(buf)) {
		bp = malloc(len);
		if (bp == NULL) {
			printf("EAPOL frame discarded, cannot malloc temp "
				"buffer of size %u!\n", len);
			return -1;
		}
	}
	eth = (struct l2_ethhdr *) bp;
	memcpy(eth->h_dest, addr, ETH_ALEN);
	memcpy(eth->h_source, drv->hapd->own_addr, ETH_ALEN);
	eth->h_proto = htons(ETH_P_EAPOL);
	memcpy(eth+1, data, data_len);

	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
		hostapd_hexdump("TX EAPOL", bp, len);

	status = l2_packet_send(drv->sock_xmit, bp, len);

	if (bp != buf)
		free(bp);
	return status;
}
Beispiel #4
0
int radius_client_send(struct wpa_supplicant *wpa_s, struct radius_msg *msg,
		       RadiusType msg_type, u8 *addr)
{
	u8 *shared_secret;
	size_t shared_secret_len;
	char *name;
	int s, res;

	if (msg_type == RADIUS_ACCT_INTERIM) {
		/* Remove any pending interim acct update for the same STA. */
		radius_client_list_del(wpa_s, msg_type, addr);
	}

	if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
		shared_secret = wpa_s->acct_server->shared_secret;
		shared_secret_len = wpa_s->acct_server->shared_secret_len;
		radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
		name = "accounting";
		s = wpa_s->radius->acct_serv_sock;
	} else {
		shared_secret = wpa_s->auth_server->shared_secret;
		shared_secret_len = wpa_s->auth_server->shared_secret_len;
		radius_msg_finish(msg, shared_secret, shared_secret_len);
		name = "authentication";
		s = wpa_s->radius->auth_serv_sock;
	}

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		      "Sending RADIUS message to %s server\n", name);
	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
		radius_msg_dump(msg);

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

	radius_client_list_add(wpa_s, msg, msg_type, shared_secret,
			       shared_secret_len, addr);

	return res;
}
Beispiel #5
0
static void handle_beacon(hostapd *hapd, struct ieee80211_mgmt *mgmt,
                          size_t len)
{
    struct ieee802_11_elems elems;

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

    (void) ieee802_11_parse_elems(hapd, mgmt->u.beacon.variable,
                                  len - (IEEE80211_HDRLEN +
                                         sizeof(mgmt->u.beacon)), &elems,
                                  0);

    if (hapd->assoc_ap_state == WAIT_BEACON &&
            memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
        if (elems.ssid && elems.ssid_len <= 32) {
            memcpy(hapd->assoc_ap_ssid, elems.ssid,
                   elems.ssid_len);
            hapd->assoc_ap_ssid[elems.ssid_len] = '\0';
            hapd->assoc_ap_ssid_len = elems.ssid_len;
        }
        ieee802_11_sta_authenticate(hapd, NULL);
    }

    if (!HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_EXCESSIVE))
        return;

    printf("Beacon from " MACSTR, MAC2STR(mgmt->sa));
    if (elems.ssid) {
        printf(" SSID='");
        ieee802_11_print_ssid(elems.ssid, elems.ssid_len);
        printf("'");
    }
    if (elems.ds_params && elems.ds_params_len == 1)
        printf(" CHAN=%d", elems.ds_params[0]);
    printf("\n");
}
Beispiel #6
0
/* The rekeying function: generate a new broadcast WEP key, rotate
 * the key index, and direct Key Transmit State Machines of all of the
 * authenticators to send a new key to the authenticated stations.
 */
static void hostapd_rotate_wep(void *eloop_ctx, void *timeout_ctx)
{
	struct sta_info *s;
	hostapd *hapd = eloop_ctx;

	if (hapd->default_wep_key)
		free(hapd->default_wep_key);

	if (hapd->default_wep_key_idx >= 3)
		hapd->default_wep_key_idx =
			hapd->conf->individual_wep_key_len > 0 ? 1 : 0;
	else
		hapd->default_wep_key_idx++;

	hostapd_set_broadcast_wep(hapd);

	for (s = hapd->sta_list; s != NULL; s = s->next)
		ieee802_1x_notify_key_available(s->eapol_sm, 1);

	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) {
		hostapd_hexdump("New WEP key generated",
				hapd->default_wep_key,
				hapd->conf->default_wep_key_len);
	}

	/* TODO: Could setup key for RX here, but change default TX keyid only
	 * after new broadcast key has been sent to all stations. */
	if (hostapd_set_encryption(hapd->driver.data, "WEP", NULL,
				   hapd->default_wep_key_idx,
				   hapd->default_wep_key,
				   hapd->conf->default_wep_key_len)) {
		printf("Could not set WEP encryption.\n");
	}

	if (hapd->conf->wep_rekeying_period > 0)
		eloop_register_timeout(hapd->conf->wep_rekeying_period, 0,
				       hostapd_rotate_wep, hapd, NULL);
}
Beispiel #7
0
static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
{
	hostapd *hapd = (hostapd *) eloop_ctx;
	int len;
	unsigned char buf[3000];

	len = recv(sock, buf, sizeof(buf), 0);
	if (len < 0) {
		perror("recv");
		return;
	}
	HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE,
		      "Received %d bytes management frame\n", len);
	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) {
		int i;
		printf("  dump:");
		for (i = 0; i < len; i++)
			printf(" %02x", buf[i]);
		printf("\n");
	}

	handle_frame(hapd, buf, len);
}
int radius_client_send(hostapd *hapd, struct radius_msg *msg,
		       RadiusType msg_type)
{
	u8 *shared_secret;
	size_t shared_secret_len;
	char *name;
	int s, res;

	if (msg_type == RADIUS_ACCT) {
		shared_secret = hapd->conf->acct_server->shared_secret;
		shared_secret_len = hapd->conf->acct_server->shared_secret_len;
		radius_msg_finish_acct(msg, shared_secret, shared_secret_len);
		name = "accounting";
		s = hapd->radius->acct_serv_sock;
	} else {
		shared_secret = hapd->conf->auth_server->shared_secret;
		shared_secret_len = hapd->conf->auth_server->shared_secret_len;
		radius_msg_finish(msg, shared_secret, shared_secret_len);
		name = "authentication";
		s = hapd->radius->auth_serv_sock;
	}

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		      "Sending RADIUS message to %s server\n", name);
	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
		radius_msg_dump(msg);

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

	radius_client_list_add(hapd, msg, msg_type, shared_secret,
			       shared_secret_len);

	return res;
}
Beispiel #9
0
ParseRes ieee802_11_parse_elems(struct hostapd_data *hapd, u8 *start,
                                size_t len,
                                struct ieee802_11_elems *elems,
                                int show_errors)
{
    size_t left = len;
    u8 *pos = start;
    int unknown = 0;

    memset(elems, 0, sizeof(*elems));

    while (left >= 2) {
        u8 id, elen;

        id = *pos++;
        elen = *pos++;
        left -= 2;

        if (elen > left) {
            if (show_errors) {
                HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                              "IEEE 802.11 element parse "
                              "failed (id=%d elen=%d "
                              "left=%lu)\n",
                              id, elen, (unsigned long) left);
                if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL))
                    hostapd_hexdump("IEs", start, len);
            }
            return ParseFailed;
        }

        switch (id) {
        case WLAN_EID_SSID:
            elems->ssid = pos;
            elems->ssid_len = elen;
            break;
        case WLAN_EID_SUPP_RATES:
            elems->supp_rates = pos;
            elems->supp_rates_len = elen;
            break;
        case WLAN_EID_FH_PARAMS:
            elems->fh_params = pos;
            elems->fh_params_len = elen;
            break;
        case WLAN_EID_DS_PARAMS:
            elems->ds_params = pos;
            elems->ds_params_len = elen;
            break;
        case WLAN_EID_CF_PARAMS:
            elems->cf_params = pos;
            elems->cf_params_len = elen;
            break;
        case WLAN_EID_TIM:
            elems->tim = pos;
            elems->tim_len = elen;
            break;
        case WLAN_EID_IBSS_PARAMS:
            elems->ibss_params = pos;
            elems->ibss_params_len = elen;
            break;
        case WLAN_EID_CHALLENGE:
            elems->challenge = pos;
            elems->challenge_len = elen;
            break;
        case WLAN_EID_GENERIC:
            if (elen > 4 && memcmp(pos, WPA_OUI_TYPE, 4) == 0) {
                elems->wpa_ie = pos;
                elems->wpa_ie_len = elen;
            } else if (show_errors) {
                HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE,
                              "IEEE 802.11 element parse "
                              "ignored unknown generic element"
                              " (id=%d elen=%d OUI:type="
                              "%02x-%02x-%02x:%d)\n",
                              id, elen,
                              elen >= 1 ? pos[0] : 0,
                              elen >= 2 ? pos[1] : 0,
                              elen >= 3 ? pos[2] : 0,
                              elen >= 4 ? pos[3] : 0);
                unknown++;
            } else {
                unknown++;
            }
            break;
        case WLAN_EID_RSN:
            elems->rsn_ie = pos;
            elems->rsn_ie_len = elen;
            break;
        default:
            unknown++;
            if (!show_errors)
                break;
            HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE,
                          "IEEE 802.11 element parse ignored "
                          "unknown element (id=%d elen=%d)\n",
                          id, elen);
            break;
        }

        left -= elen;
        pos += elen;
    }

    if (left)
        return ParseFailed;

    return unknown ? ParseUnknown : ParseOK;
}
static int hostapd_setup_interface(struct hostapd_data *hapd)
{
	struct hostapd_config *conf = hapd->conf;
	u8 ssid[HOSTAPD_SSID_LEN + 1];
	int ssid_len, set_ssid;
	int ret = 0;

	if (hostapd_driver_init(hapd)) {
		printf("%s driver initialization failed.\n",
			hapd->driver ? hapd->driver->name : "Unknown");
		hapd->driver = NULL;
		return -1;
	}

	/*
	 * Fetch the SSID from the system and use it or,
	 * if one was specified in the config file, verify they
	 * match.
	 */
	ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
	if (ssid_len < 0) {
		printf("Could not read SSID from system\n");
		return -1;
	}
	if (conf->ssid_set) {
		/*
		 * If SSID is specified in the config file and it differs
		 * from what is being used then force installation of the
		 * new SSID.
		 */
		set_ssid = (conf->ssid_len != ssid_len ||
			    memcmp(conf->ssid, ssid, ssid_len) != 0);
	} else {
		/*
		 * No SSID in the config file; just use the one we got
		 * from the system.
		 */
		set_ssid = 0;
		conf->ssid_len = ssid_len;
		memcpy(conf->ssid, ssid, conf->ssid_len);
		conf->ssid[conf->ssid_len] = '\0';
	}

	printf("Using interface %s with hwaddr " MACSTR " and ssid '%s'\n",
	       hapd->conf->iface, MAC2STR(hapd->own_addr), hapd->conf->ssid);

	if (hostapd_setup_wpa_psk(conf)) {
		printf("WPA-PSK setup failed.\n");
		return -1;
	}

	/* Set SSID for the kernel driver (to be used in beacon and probe
	 * response frames) */
	if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid,
					 conf->ssid_len)) {
		printf("Could not set SSID for kernel driver\n");
		return -1;
	}

	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
		conf->radius->msg_dumps = 1;
	hapd->radius = radius_client_init(hapd, conf->radius);
	if (hapd->radius == NULL) {
		printf("RADIUS client initialization failed.\n");
		return -1;
	}
	if (conf->radius_server_clients) {
		struct radius_server_conf srv;
		memset(&srv, 0, sizeof(srv));
		srv.client_file = conf->radius_server_clients;
		srv.auth_port = conf->radius_server_auth_port;
		srv.hostapd_conf = conf;
		srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
		srv.ssl_ctx = hapd->ssl_ctx;
		srv.ipv6 = conf->radius_server_ipv6;
		hapd->radius_srv = radius_server_init(&srv);
		if (hapd->radius_srv == NULL) {
			printf("RADIUS server initialization failed.\n");
			return -1;
		}
	}
	if (hostapd_acl_init(hapd)) {
		printf("ACL initialization failed.\n");
		return -1;
	}
	if (ieee802_1x_init(hapd)) {
		printf("IEEE 802.1X initialization failed.\n");
		return -1;
	}

	if (hapd->conf->wpa && wpa_init(hapd)) {
		printf("WPA initialization failed.\n");
		return -1;
	}

#ifdef SIMPLE_CONFIG
	if (wsc_ie_init(hapd) < 0)
	{
		printf("WSC IE initialization failed.\n");
		return -1;
	}
#endif

	if (accounting_init(hapd)) {
		printf("Accounting initialization failed.\n");
		return -1;
	}

	if (hapd->conf->ieee802_11f &&
	    (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
		printf("IEEE 802.11F (IAPP) initialization failed.\n");
		return -1;
	}

	if (hostapd_wireless_event_init(hapd) < 0)
		return -1;

	if (hostapd_flush_old_stations(hapd))
		return -1;

	if (hostapd_ctrl_iface_init(hapd)) {
		printf("Failed to setup control interface\n");
		ret = -1;
	}

	return ret;
}
Beispiel #11
0
static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
    struct radius_client_data *radius = eloop_ctx;
    struct hostapd_data *hapd = radius->hapd;
    RadiusType msg_type = (RadiusType) sock_ctx;
    int len, i, roundtrip;
    unsigned char buf[3000];
    struct radius_msg *msg;
    struct radius_rx_handler *handlers;
    size_t num_handlers;
    struct radius_msg_list *req, *prev_req;
    struct timeval tv;
    struct hostapd_radius_server *rconf;
    int invalid_authenticator = 0;

    if (msg_type == RADIUS_ACCT) {
        handlers = radius->acct_handlers;
        num_handlers = radius->num_acct_handlers;
        rconf = hapd->conf->acct_server;
    } else {
        handlers = radius->auth_handlers;
        num_handlers = radius->num_auth_handlers;
        rconf = hapd->conf->auth_server;
    }

    len = recv(sock, buf, sizeof(buf), 0);
    if (len < 0) {
        perror("recv[RADIUS]");
        return;
    }
    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                  "Received %d bytes from RADIUS server\n", len);
    if (len == sizeof(buf)) {
        printf("Possibly too long UDP frame for our buffer - "
               "dropping it\n");
        return;
    }

    msg = radius_msg_parse(buf, len);
    if (msg == NULL) {
        printf("Parsing incoming RADIUS frame failed\n");
        rconf->malformed_responses++;
        return;
    }

    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                  "Received RADIUS message\n");
    if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
        radius_msg_dump(msg);

    switch (msg->hdr->code) {
    case RADIUS_CODE_ACCESS_ACCEPT:
        rconf->access_accepts++;
        break;
    case RADIUS_CODE_ACCESS_REJECT:
        rconf->access_rejects++;
        break;
    case RADIUS_CODE_ACCESS_CHALLENGE:
        rconf->access_challenges++;
        break;
    case RADIUS_CODE_ACCOUNTING_RESPONSE:
        rconf->responses++;
        break;
    }

    prev_req = NULL;
    req = radius->msgs;
    while (req) {
        /* TODO: also match by src addr:port of the packet when using
         * alternative RADIUS servers (?) */
        if ((req->msg_type == msg_type ||
                (req->msg_type == RADIUS_ACCT_INTERIM &&
                 msg_type == RADIUS_ACCT)) &&
                req->msg->hdr->identifier == msg->hdr->identifier)
            break;

        prev_req = req;
        req = req->next;
    }

    if (req == NULL) {
        HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                      "No matching RADIUS request found (type=%d "
                      "id=%d) - dropping packet\n",
                      msg_type, msg->hdr->identifier);
        goto fail;
    }

    gettimeofday(&tv, NULL);
    roundtrip = (tv.tv_sec - req->last_attempt.tv_sec) * 100 +
                (tv.tv_usec - req->last_attempt.tv_usec) / 10000;
    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Received RADIUS packet matched "
                  "with a pending request, round trip time %d.%02d sec\n",
                  roundtrip / 100, roundtrip % 100);
    rconf->round_trip_time = roundtrip;

    /* Remove ACKed RADIUS packet from retransmit list */
    if (prev_req)
        prev_req->next = req->next;
    else
        radius->msgs = req->next;
    radius->num_msgs--;

    for (i = 0; i < num_handlers; i++) {
        RadiusRxResult res;
        res = handlers[i].handler(msg, req->msg, req->shared_secret,
                                  req->shared_secret_len,
                                  handlers[i].data);
        switch (res) {
        case RADIUS_RX_PROCESSED:
            radius_msg_free(msg);
            free(msg);
        /* continue */
        case RADIUS_RX_QUEUED:
            radius_client_msg_free(req);
            return;
        case RADIUS_RX_INVALID_AUTHENTICATOR:
            invalid_authenticator++;
        /* continue */
        case RADIUS_RX_UNKNOWN:
            /* continue with next handler */
            break;
        }
    }

    if (invalid_authenticator)
        rconf->bad_authenticators++;
    else
        rconf->unknown_types++;
    hostapd_logger(hapd, req->addr, HOSTAPD_MODULE_RADIUS,
                   HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
                   "(type=%d code=%d id=%d)%s - dropping packet",
                   msg_type, msg->hdr->code, msg->hdr->identifier,
                   invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
                   "");
    radius_client_msg_free(req);

fail:
    radius_msg_free(msg);
    free(msg);
}
static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
	hostapd *hapd = (hostapd *) eloop_ctx;
	RadiusType msg_type = (RadiusType) sock_ctx;
	int len, i;
	unsigned char buf[3000];
	struct radius_msg *msg;
	struct radius_rx_handler *handlers;
	size_t num_handlers;
	struct radius_msg_list *req, *prev_req;

	len = recv(sock, buf, sizeof(buf), 0);
	if (len < 0) {
		perror("recv[RADIUS]");
		return;
	}
	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		      "Received %d bytes from RADIUS server\n", len);
	if (len == sizeof(buf)) {
		printf("Possibly too long UDP frame for our buffer - "
		       "dropping it\n");
		return;
	}

	msg = radius_msg_parse(buf, len);
	if (msg == NULL) {
		printf("Parsing incoming RADIUS frame failed\n");
		return;
	}

	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
		      "Received RADIUS message\n");
	if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS))
		radius_msg_dump(msg);

	if (msg_type == RADIUS_ACCT) {
		handlers = hapd->radius->acct_handlers;
		num_handlers = hapd->radius->num_acct_handlers;
	} else {
		handlers = hapd->radius->auth_handlers;
		num_handlers = hapd->radius->num_auth_handlers;
	}

	prev_req = NULL;
	req = hapd->radius->msgs;
	while (req) {
		/* TODO: also match by src addr:port of the packet when using
		 * alternative RADIUS servers (?) */
		if (req->msg_type == msg_type &&
		    req->msg->hdr->identifier == msg->hdr->identifier)
			break;

		prev_req = req;
		req = req->next;
	}

	if (req == NULL) {
		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
			      "No maching RADIUS request found (type=%d id=%d)"
			      " - dropping packet\n",
			      msg_type, msg->hdr->identifier);
		goto fail;
	}

	/* Remove ACKed RADIUS packet from retransmit list */
	if (prev_req)
		prev_req->next = req->next;
	else
		hapd->radius->msgs = req->next;
	hapd->radius->num_msgs--;

	for (i = 0; i < num_handlers; i++) {
		RadiusRxResult res;
		res = handlers[i].handler(hapd, msg, req->msg,
					  req->shared_secret,
					  req->shared_secret_len,
					  handlers[i].data);
		switch (res) {
		case RADIUS_RX_PROCESSED:
			radius_msg_free(msg);
			free(msg);
			/* continue */
		case RADIUS_RX_QUEUED:
			radius_client_msg_free(req);
			return;
		case RADIUS_RX_UNKNOWN:
			/* continue with next handler */
			break;
		}
	}

	printf("No RADIUS RX handler found (type=%d code=%d id=%d) - dropping "
	       "packet\n", msg_type, msg->hdr->code, msg->hdr->identifier);
	radius_client_msg_free(req);

 fail:
	radius_msg_free(msg);
	free(msg);
}
Beispiel #13
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;
	}
}