X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=hostapd%2Fctrl_iface.c;h=9758881bb2df04cccd7cc6be93316f6bd11b3b58;hb=53661e3a9af377a540368f155851373c592ff5a7;hp=0233b78780e6f2e726428cb255bc3901305560bd;hpb=cc79e06f0053ac85f04f08376a2269c634154c87;p=thirdparty%2Fhostap.git diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 0233b7878..9758881bb 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1,6 +1,6 @@ /* * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004-2015, Jouni Malinen + * Copyright (c) 2004-2018, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -29,7 +29,9 @@ #include "common/version.h" #include "common/ieee802_11_defs.h" #include "common/ctrl_iface_common.h" +#ifdef CONFIG_DPP #include "common/dpp.h" +#endif /* CONFIG_DPP */ #include "common/wpa_ctrl.h" #include "crypto/tls.h" #include "drivers/driver.h" @@ -128,7 +130,6 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, } -#ifdef CONFIG_IEEE80211W #ifdef NEED_AP_MLME static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, const char *txtaddr) @@ -147,7 +148,6 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, return 0; } #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS @@ -881,7 +881,7 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, /* TODO: TSF configurable/learnable */ bss_term_dur[0] = 4; /* Subelement ID */ bss_term_dur[1] = 10; /* Length */ - os_memset(bss_term_dur, 2, 8); + os_memset(&bss_term_dur[2], 0, 8); end = os_strchr(pos, ','); if (end == NULL) { wpa_printf(MSG_DEBUG, "Invalid bss_term data"); @@ -990,6 +990,42 @@ fail: return ret; } + +static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd, + const char *cmd) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + const char *pos; + unsigned int auto_report, timeout; + + if (hwaddr_aton(cmd, addr)) { + wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); + return -1; + } + + sta = ap_get_sta(hapd, addr); + if (!sta) { + wpa_printf(MSG_DEBUG, "Station " MACSTR + " not found for Collocated Interference Request", + MAC2STR(addr)); + return -1; + } + + pos = cmd + 17; + if (*pos != ' ') + return -1; + pos++; + auto_report = atoi(pos); + pos = os_strchr(pos, ' '); + if (!pos) + return -1; + pos++; + timeout = atoi(pos); + + return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout); +} + #endif /* CONFIG_WNM_AP */ @@ -1029,6 +1065,14 @@ static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, return pos - buf; pos += ret; } +#ifdef CONFIG_SHA384 + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) { + ret = os_snprintf(pos, end - pos, "FT-EAP-SHA384 "); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SHA384 */ #ifdef CONFIG_SAE if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { ret = os_snprintf(pos, end - pos, "FT-SAE "); @@ -1052,7 +1096,6 @@ static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, } #endif /* CONFIG_FILS */ #endif /* CONFIG_IEEE80211R_AP */ -#ifdef CONFIG_IEEE80211W if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); if (os_snprintf_error(end - pos, ret)) @@ -1065,7 +1108,6 @@ static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, return pos - buf; pos += ret; } -#endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_SAE if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { ret = os_snprintf(pos, end - pos, "SAE "); @@ -1248,6 +1290,69 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, } +static void hostapd_disassoc_accept_mac(struct hostapd_data *hapd) +{ + struct sta_info *sta; + struct vlan_description vlan_id; + + if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED) + return; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (!hostapd_maclist_found(hapd->conf->accept_mac, + hapd->conf->num_accept_mac, + sta->addr, &vlan_id) || + (vlan_id.notempty && + vlan_compare(&vlan_id, sta->vlan_desc))) + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_UNSPECIFIED); + } +} + + +static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd) +{ + struct sta_info *sta; + struct vlan_description vlan_id; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (hostapd_maclist_found(hapd->conf->deny_mac, + hapd->conf->num_deny_mac, sta->addr, + &vlan_id) && + (!vlan_id.notempty || + !vlan_compare(&vlan_id, sta->vlan_desc))) + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_UNSPECIFIED); + } +} + + +static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd, + const char *band) +{ + union wpa_event_data event; + enum set_band setband; + + if (os_strcmp(band, "AUTO") == 0) + setband = WPA_SETBAND_AUTO; + else if (os_strcmp(band, "5G") == 0) + setband = WPA_SETBAND_5G; + else if (os_strcmp(band, "2G") == 0) + setband = WPA_SETBAND_2G; + else + return -1; + + if (hostapd_drv_set_band(hapd, setband) == 0) { + os_memset(&event, 0, sizeof(event)); + event.channel_list_changed.initiator = REGDOM_SET_BY_USER; + event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; + wpa_supplicant_event(hapd, EVENT_CHANNEL_LIST_CHANGED, &event); + } + + return 0; +} + + static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) { char *value; @@ -1331,39 +1436,28 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) os_free(hapd->dpp_configurator_params); hapd->dpp_configurator_params = os_strdup(value); #endif /* CONFIG_DPP */ + } else if (os_strcasecmp(cmd, "setband") == 0) { + ret = hostapd_ctrl_iface_set_band(hapd, value); } else { - struct sta_info *sta; - struct vlan_description vlan_id; - ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); if (ret) return ret; if (os_strcasecmp(cmd, "deny_mac_file") == 0) { - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (hostapd_maclist_found( - hapd->conf->deny_mac, - hapd->conf->num_deny_mac, sta->addr, - &vlan_id) && - (!vlan_id.notempty || - !vlan_compare(&vlan_id, sta->vlan_desc))) - ap_sta_disconnect( - hapd, sta, sta->addr, - WLAN_REASON_UNSPECIFIED); - } - } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED && - os_strcasecmp(cmd, "accept_mac_file") == 0) { - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (!hostapd_maclist_found( - hapd->conf->accept_mac, - hapd->conf->num_accept_mac, - sta->addr, &vlan_id) || - (vlan_id.notempty && - vlan_compare(&vlan_id, sta->vlan_desc))) - ap_sta_disconnect( - hapd, sta, sta->addr, - WLAN_REASON_UNSPECIFIED); - } + hostapd_disassoc_deny_mac(hapd); + } else if (os_strcasecmp(cmd, "accept_mac_file") == 0) { + hostapd_disassoc_accept_mac(hapd); + } else if (os_strncmp(cmd, "wme_ac_", 7) == 0 || + os_strncmp(cmd, "wmm_ac_", 7) == 0) { + hapd->parameter_set_count++; + if (ieee802_11_update_beacons(hapd->iface)) + wpa_printf(MSG_DEBUG, + "Failed to update beacons with WMM parameters"); + } else if (os_strcmp(cmd, "wpa_passphrase") == 0 || + os_strcmp(cmd, "sae_password") == 0 || + os_strcmp(cmd, "sae_pwe") == 0) { + if (hapd->started) + hostapd_setup_sae_pt(hapd->conf); } } @@ -1424,6 +1518,63 @@ static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) } +static int +hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd, + struct sta_info *sta, void *ctx) +{ + struct hostapd_wpa_psk *psk; + const u8 *pmk; + int pmk_len; + int pmk_match; + int sta_match; + int bss_match; + int reason; + + pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); + + for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) { + pmk_match = PMK_LEN == pmk_len && + os_memcmp(psk->psk, pmk, pmk_len) == 0; + sta_match = psk->group == 0 && + os_memcmp(sta->addr, psk->addr, ETH_ALEN) == 0; + bss_match = psk->group == 1; + + if (pmk_match && (sta_match || bss_match)) + return 0; + } + + wpa_printf(MSG_INFO, "STA " MACSTR + " PSK/passphrase no longer valid - disconnect", + MAC2STR(sta->addr)); + reason = WLAN_REASON_PREV_AUTH_NOT_VALID; + hostapd_drv_sta_deauth(hapd, sta->addr, reason); + ap_sta_deauthenticate(hapd, sta, reason); + + return 0; +} + + +static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd) +{ + struct hostapd_bss_config *conf = hapd->conf; + int err; + + hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk); + + err = hostapd_setup_wpa_psk(conf); + if (err < 0) { + wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d", + err); + return -1; + } + + ap_for_each_sta(hapd, hostapd_ctrl_iface_kick_mismatch_psk_sta_iter, + NULL); + + return 0; +} + + #ifdef CONFIG_TESTING_OPTIONS static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) @@ -1709,26 +1860,40 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, struct iphdr ip; const u8 *pos; unsigned int i; + char extra[30]; - if (len != HWSIM_PACKETLEN) + if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { + wpa_printf(MSG_DEBUG, + "test data: RX - ignore unexpected length %d", + (int) len); return; + } eth = (const struct ether_header *) buf; os_memcpy(&ip, eth + 1, sizeof(ip)); pos = &buf[sizeof(*eth) + sizeof(ip)]; if (ip.ihl != 5 || ip.version != 4 || - ntohs(ip.tot_len) != HWSIM_IP_LEN) + ntohs(ip.tot_len) > HWSIM_IP_LEN) { + wpa_printf(MSG_DEBUG, + "test data: RX - ignore unexpect IP header"); return; + } - for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) { - if (*pos != (u8) i) + for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) { + if (*pos != (u8) i) { + wpa_printf(MSG_DEBUG, + "test data: RX - ignore mismatching payload"); return; + } pos++; } - wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR, - MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost)); + extra[0] = '\0'; + if (ntohs(ip.tot_len) != HWSIM_IP_LEN) + os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len)); + wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", + MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); } @@ -1773,7 +1938,7 @@ static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd, static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) { u8 dst[ETH_ALEN], src[ETH_ALEN]; - char *pos; + char *pos, *pos2; int used; long int val; u8 tos; @@ -1782,11 +1947,12 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) struct iphdr *ip; u8 *dpos; unsigned int i; + size_t send_len = HWSIM_IP_LEN; if (hapd->l2_test == NULL) return -1; - /* format: */ + /* format: [len=] */ pos = cmd; used = hwaddr_aton2(pos, dst); @@ -1800,11 +1966,19 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) return -1; pos += used; - val = strtol(pos, NULL, 0); + val = strtol(pos, &pos2, 0); if (val < 0 || val > 0xff) return -1; tos = val; + pos = os_strstr(pos2, " len="); + if (pos) { + i = atoi(pos + 5); + if (i < sizeof(*ip) || i > HWSIM_IP_LEN) + return -1; + send_len = i; + } + eth = (struct ether_header *) &buf[2]; os_memcpy(eth->ether_dhost, dst, ETH_ALEN); os_memcpy(eth->ether_shost, src, ETH_ALEN); @@ -1815,17 +1989,17 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) ip->version = 4; ip->ttl = 64; ip->tos = tos; - ip->tot_len = htons(HWSIM_IP_LEN); + ip->tot_len = htons(send_len); ip->protocol = 1; ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); dpos = (u8 *) (ip + 1); - for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) + for (i = 0; i < send_len - sizeof(*ip); i++) *dpos++ = i; if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2], - HWSIM_PACKETLEN) < 0) + sizeof(struct ether_header) + send_len) < 0) return -1; wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR @@ -1965,7 +2139,6 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) if (hwaddr_aton(cmd, addr)) return -1; -#ifdef CONFIG_IEEE80211W if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) { if (hapd->last_igtk_alg == WPA_ALG_NONE) return -1; @@ -1989,7 +2162,6 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) hapd->last_igtk, hapd->last_igtk_len); } -#endif /* CONFIG_IEEE80211W */ if (is_broadcast_ether_addr(addr)) { if (hapd->last_gtk_alg == WPA_ALG_NONE) @@ -2070,7 +2242,7 @@ static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd) if (!pos) return -1; pos++; - if (hexstr2bin(pos, seq, sizeof(6)) < 0) + if (hexstr2bin(pos, seq, sizeof(seq)) < 0) return -1; pos += 2 * 6; if (*pos != ' ') @@ -2208,6 +2380,11 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, return ret; for (i = 0; i < iface->num_bss; i++) { + + /* Save CHAN_SWITCH VHT config */ + hostapd_chan_switch_vht_config( + iface->bss[i], settings.freq_params.vht_enabled); + ret = hostapd_switch_channel(iface->bss[i], &settings); if (ret) { /* FIX: What do we do if CSA fails in the middle of @@ -2530,6 +2707,20 @@ static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd, } +static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd, + char *buf, size_t buflen) +{ + if (!(hapd->conf->radio_measurements[0] & + WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { + wpa_printf(MSG_ERROR, + "CTRL: SHOW_NEIGHBOR: Neighbor report is not enabled"); + return -1; + } + + return hostapd_neighbor_show(hapd, buf, buflen); +} + + static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf) { struct wpa_ssid_value ssid; @@ -2636,6 +2827,7 @@ static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, char *buf) { struct wpa_ssid_value ssid; + struct wpa_ssid_value *ssidp = NULL; u8 bssid[ETH_ALEN]; char *tmp; @@ -2645,13 +2837,16 @@ static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, } tmp = os_strstr(buf, "ssid="); - if (!tmp || ssid_parse(tmp + 5, &ssid)) { - wpa_printf(MSG_ERROR, - "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID"); - return -1; + if (tmp) { + ssidp = &ssid; + if (ssid_parse(tmp + 5, &ssid)) { + wpa_printf(MSG_ERROR, + "CTRL: REMOVE_NEIGHBOR: Bad SSID"); + return -1; + } } - return hostapd_neighbor_remove(hapd, bssid, &ssid); + return hostapd_neighbor_remove(hapd, bssid, ssidp); } @@ -2683,6 +2878,108 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, } +static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, + const char *txtaddr) +{ + u8 addr[ETH_ALEN]; + struct vlan_description vlan_id; + + if (!(*num)) + return 0; + + if (hwaddr_aton(txtaddr, addr)) + return -1; + + if (hostapd_maclist_found(*acl, *num, addr, &vlan_id)) + hostapd_remove_acl_mac(acl, num, addr); + + return 0; +} + + +static void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, + int *num) +{ + while (*num) + hostapd_remove_acl_mac(acl, num, (*acl)[0].addr); +} + + +static int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, + char *buf, size_t buflen) +{ + int i = 0, len = 0, ret = 0; + + if (!acl) + return 0; + + while (i < num) { + ret = os_snprintf(buf + len, buflen - len, + MACSTR " VLAN_ID=%d\n", + MAC2STR(acl[i].addr), + acl[i].vlan_id.untagged); + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + i++; + len += ret; + } + return len; +} + + +static int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, + const char *cmd) +{ + u8 addr[ETH_ALEN]; + struct vlan_description vlan_id; + int ret = 0, vlanid = 0; + const char *pos; + + if (hwaddr_aton(cmd, addr)) + return -1; + + pos = os_strstr(cmd, "VLAN_ID="); + if (pos) + vlanid = atoi(pos + 8); + + if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) { + ret = hostapd_add_acl_maclist(acl, num, vlanid, addr); + if (ret != -1 && *acl) + qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); + } + + return ret < 0 ? -1 : 0; +} + + +static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd, + const char *field, char *buf, + size_t buflen) +{ + wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field); + +#ifdef CONFIG_DPP + if (os_strcmp(field, "dpp") == 0) { + int res; + +#ifdef CONFIG_DPP2 + res = os_snprintf(buf, buflen, "DPP=2"); +#else /* CONFIG_DPP2 */ + res = os_snprintf(buf, buflen, "DPP=1"); +#endif /* CONFIG_DPP2 */ + if (os_snprintf_error(buflen, res)) + return -1; + return res; + } +#endif /* CONFIG_DPP */ + + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", + field); + + return -1; +} + + static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, char *buf, char *reply, int reply_size, @@ -2700,6 +2997,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "RELOG", 5) == 0) { if (wpa_debug_reopen_file() < 0) reply_len = -1; + } else if (os_strncmp(buf, "NOTE ", 5) == 0) { + wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); } else if (os_strcmp(buf, "STATUS") == 0) { reply_len = hostapd_ctrl_iface_status(hapd, reply, reply_size); @@ -2779,13 +3078,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strcmp(buf, "STOP_AP") == 0) { if (hostapd_ctrl_iface_stop_ap(hapd)) reply_len = -1; -#ifdef CONFIG_IEEE80211W #ifdef NEED_AP_MLME } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) reply_len = -1; #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) @@ -2852,6 +3149,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11)) reply_len = -1; + } else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) { + if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15)) + reply_len = -1; #endif /* CONFIG_WNM_AP */ } else if (os_strcmp(buf, "GET_CONFIG") == 0) { reply_len = hostapd_ctrl_iface_get_config(hapd, reply, @@ -2865,6 +3165,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "ENABLE", 6) == 0) { if (hostapd_ctrl_iface_enable(hapd->iface)) reply_len = -1; + } else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) { + if (hostapd_ctrl_iface_reload_wpa_psk(hapd)) + reply_len = -1; } else if (os_strncmp(buf, "RELOAD", 6) == 0) { if (hostapd_ctrl_iface_reload(hapd->iface)) reply_len = -1; @@ -2966,6 +3269,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) { if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13)) reply_len = -1; + } else if (os_strcmp(buf, "SHOW_NEIGHBOR") == 0) { + reply_len = hostapd_ctrl_iface_show_neighbor(hapd, reply, + reply_size); } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) { if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16)) reply_len = -1; @@ -2983,6 +3289,46 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_size); } else if (os_strcmp(buf, "TERMINATE") == 0) { eloop_terminate(); + } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { + if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { + if (!hostapd_ctrl_iface_acl_add_mac( + &hapd->conf->accept_mac, + &hapd->conf->num_accept_mac, buf + 19)) + hostapd_disassoc_accept_mac(hapd); + else + reply_len = -1; + } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { + hostapd_ctrl_iface_acl_del_mac( + &hapd->conf->accept_mac, + &hapd->conf->num_accept_mac, buf + 19); + } else if (os_strcmp(buf + 11, "SHOW") == 0) { + reply_len = hostapd_ctrl_iface_acl_show_mac( + hapd->conf->accept_mac, + hapd->conf->num_accept_mac, reply, reply_size); + } else if (os_strcmp(buf + 11, "CLEAR") == 0) { + hostapd_ctrl_iface_acl_clear_list( + &hapd->conf->accept_mac, + &hapd->conf->num_accept_mac); + } + } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { + if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { + if (!hostapd_ctrl_iface_acl_add_mac( + &hapd->conf->deny_mac, + &hapd->conf->num_deny_mac, buf + 17)) + hostapd_disassoc_deny_mac(hapd); + } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { + hostapd_ctrl_iface_acl_del_mac( + &hapd->conf->deny_mac, + &hapd->conf->num_deny_mac, buf + 17); + } else if (os_strcmp(buf + 9, "SHOW") == 0) { + reply_len = hostapd_ctrl_iface_acl_show_mac( + hapd->conf->deny_mac, + hapd->conf->num_deny_mac, reply, reply_size); + } else if (os_strcmp(buf + 9, "CLEAR") == 0) { + hostapd_ctrl_iface_acl_clear_list( + &hapd->conf->deny_mac, + &hapd->conf->num_deny_mac); + } #ifdef CONFIG_DPP } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { res = hostapd_dpp_qr_code(hapd, buf + 12); @@ -2993,8 +3339,17 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, if (os_snprintf_error(reply_size, reply_len)) reply_len = -1; } + } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) { + res = hostapd_dpp_nfc_uri(hapd, buf + 12); + if (res < 0) { + reply_len = -1; + } else { + reply_len = os_snprintf(reply, reply_size, "%d", res); + if (os_snprintf_error(reply_size, reply_len)) + reply_len = -1; + } } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { - res = hostapd_dpp_bootstrap_gen(hapd, buf + 18); + res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18); if (res < 0) { reply_len = -1; } else { @@ -3003,12 +3358,14 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; } } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { - if (hostapd_dpp_bootstrap_remove(hapd, buf + 21) < 0) + if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp, + buf + 21) < 0) reply_len = -1; } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { const char *uri; - uri = hostapd_dpp_bootstrap_get_uri(hapd, atoi(buf + 22)); + uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp, + atoi(buf + 22)); if (!uri) { reply_len = -1; } else { @@ -3017,8 +3374,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; } } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { - reply_len = hostapd_dpp_bootstrap_info(hapd, atoi(buf + 19), - reply, reply_size); + reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp, + atoi(buf + 19), + reply, reply_size); } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { if (hostapd_dpp_auth_init(hapd, buf + 13) < 0) reply_len = -1; @@ -3029,7 +3387,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, hostapd_dpp_stop(hapd); hostapd_dpp_listen_stop(hapd); } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { - res = hostapd_dpp_configurator_add(hapd, buf + 20); + res = dpp_configurator_add(hapd->iface->interfaces->dpp, + buf + 20); if (res < 0) { reply_len = -1; } else { @@ -3038,8 +3397,17 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = -1; } } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { - if (hostapd_dpp_configurator_remove(hapd, buf + 24) < 0) + if (dpp_configurator_remove(hapd->iface->interfaces->dpp, + buf + 24) < 0) reply_len = -1; + } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { + if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { + reply_len = dpp_configurator_get_key_id( + hapd->iface->interfaces->dpp, + atoi(buf + 25), + reply, reply_size); } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { res = hostapd_dpp_pkex_add(hapd, buf + 12); if (res < 0) { @@ -3053,6 +3421,14 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0) reply_len = -1; #endif /* CONFIG_DPP */ +#ifdef RADIUS_SERVER + } else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) { + if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0) + reply_len = -1; +#endif /* RADIUS_SERVER */ + } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { + reply_len = hostapd_ctrl_iface_get_capability( + hapd, buf + 15, reply, reply_size); } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; @@ -3306,18 +3682,18 @@ fail: } if (hapd->conf->ctrl_interface_gid_set && - chown(hapd->conf->ctrl_interface, -1, - hapd->conf->ctrl_interface_gid) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", + lchown(hapd->conf->ctrl_interface, -1, + hapd->conf->ctrl_interface_gid) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", strerror(errno)); return -1; } if (!hapd->conf->ctrl_interface_gid_set && hapd->iface->interfaces->ctrl_iface_group && - chown(hapd->conf->ctrl_interface, -1, - hapd->iface->interfaces->ctrl_iface_group) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", + lchown(hapd->conf->ctrl_interface, -1, + hapd->iface->interfaces->ctrl_iface_group) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", strerror(errno)); return -1; } @@ -3390,16 +3766,16 @@ fail: } if (hapd->conf->ctrl_interface_gid_set && - chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", + lchown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s", strerror(errno)); goto fail; } if (!hapd->conf->ctrl_interface_gid_set && hapd->iface->interfaces->ctrl_iface_group && - chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", + lchown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s", strerror(errno)); goto fail; } @@ -3532,6 +3908,9 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) #endif /* CONFIG_DPP */ #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP + dpp_global_clear(interfaces->dpp); +#endif /* CONFIG_DPP */ } @@ -4044,6 +4423,8 @@ try_again: return -1; } + wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); + return 0; fail: @@ -4070,9 +4451,9 @@ fail: goto fail; } } else if (interface->ctrl_iface_group && - chown(interface->global_iface_path, -1, - interface->ctrl_iface_group) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", + lchown(interface->global_iface_path, -1, + interface->ctrl_iface_group) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", strerror(errno)); goto fail; } @@ -4129,8 +4510,8 @@ fail: } if (interface->ctrl_iface_group && - chown(fname, -1, interface->ctrl_iface_group) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", + lchown(fname, -1, interface->ctrl_iface_group) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", strerror(errno)); goto fail; } @@ -4146,6 +4527,8 @@ fail: eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, interface, NULL); + wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); + return 0; fail: @@ -4215,37 +4598,48 @@ static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst, } -static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, - enum wpa_msg_type type, - const char *buf, size_t len) +static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst, + const char *ifname, int level, + const char *buf, size_t len) { struct wpa_ctrl_dst *dst, *next; - struct dl_list *ctrl_dst; struct msghdr msg; - int idx; - struct iovec io[2]; + int idx, res; + struct iovec io[5]; char levelstr[10]; - int s; - - if (type != WPA_MSG_ONLY_GLOBAL) { - s = hapd->ctrl_sock; - ctrl_dst = &hapd->ctrl_dst; - } else { - s = hapd->iface->interfaces->global_ctrl_sock; - ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst; - } - if (s < 0 || dl_list_empty(ctrl_dst)) + if (sock < 0 || dl_list_empty(ctrl_dst)) return; - os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); - io[0].iov_base = levelstr; - io[0].iov_len = os_strlen(levelstr); - io[1].iov_base = (char *) buf; - io[1].iov_len = len; + res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); + if (os_snprintf_error(sizeof(levelstr), res)) + return; + idx = 0; + if (ifname) { +#ifdef CONFIG_CTRL_IFACE_UDP + io[idx].iov_base = "IFACE="; + io[idx].iov_len = 6; +#else /* CONFIG_CTRL_IFACE_UDP */ + io[idx].iov_base = "IFNAME="; + io[idx].iov_len = 7; +#endif /* CONFIG_CTRL_IFACE_UDP */ + 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 = 2; + msg.msg_iovlen = idx; idx = 0; dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) { @@ -4255,22 +4649,16 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, &dst->addr, dst->addrlen); msg.msg_name = &dst->addr; msg.msg_namelen = dst->addrlen; - if (sendmsg(s, &msg, 0) < 0) { + if (sendmsg(sock, &msg, 0) < 0) { int _errno = errno; wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " "%d - %s", idx, errno, strerror(errno)); dst->errors++; if (dst->errors > 10 || _errno == ENOENT) { - if (type != WPA_MSG_ONLY_GLOBAL) - hostapd_ctrl_iface_detach( - hapd, &dst->addr, - dst->addrlen); - else - hostapd_global_ctrl_iface_detach( - hapd->iface->interfaces, - &dst->addr, - dst->addrlen); + ctrl_iface_detach(ctrl_dst, + &dst->addr, + dst->addrlen); } } else dst->errors = 0; @@ -4279,4 +4667,25 @@ static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, } } + +static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, + enum wpa_msg_type type, + const char *buf, size_t len) +{ + if (type != WPA_MSG_NO_GLOBAL) { + hostapd_ctrl_iface_send_internal( + hapd->iface->interfaces->global_ctrl_sock, + &hapd->iface->interfaces->global_ctrl_dst, + type != WPA_MSG_PER_INTERFACE ? + NULL : hapd->conf->iface, + level, buf, len); + } + + if (type != WPA_MSG_ONLY_GLOBAL) { + hostapd_ctrl_iface_send_internal( + hapd->ctrl_sock, &hapd->ctrl_dst, + NULL, level, buf, len); + } +} + #endif /* CONFIG_NATIVE_WINDOWS */