]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - hostapd/ctrl_iface.c
Use IFNAME= prefix for global UDP control interface events
[thirdparty/hostap.git] / hostapd / ctrl_iface.c
index 8692284d126cb6a299c9084cc83a6ccb482094b0..18cbc76e5f1b31000fdc7af8a45cc711b52fcf4c 100644 (file)
 #ifndef CONFIG_NATIVE_WINDOWS
 
 #ifdef CONFIG_TESTING_OPTIONS
+#ifdef __NetBSD__
+#include <net/if_ether.h>
+#else
 #include <net/ethernet.h>
+#endif
 #include <netinet/ip.h>
 #endif /* CONFIG_TESTING_OPTIONS */
 
@@ -1658,7 +1662,7 @@ static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
                return -1;
        }
 
-       res = hostapd_drv_send_mlme(hapd, buf, len, 0);
+       res = hostapd_drv_send_mlme(hapd, buf, len, 0, NULL, 0, 0);
        os_free(buf);
        return res;
 }
@@ -1857,7 +1861,7 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
 {
        struct hostapd_data *hapd = ctx;
        const struct ether_header *eth;
-       struct iphdr ip;
+       struct ip ip;
        const u8 *pos;
        unsigned int i;
        char extra[30];
@@ -1873,14 +1877,14 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *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) {
+       if (ip.ip_hl != 5 || ip.ip_v != 4 ||
+           ntohs(ip.ip_len) > HWSIM_IP_LEN) {
                wpa_printf(MSG_DEBUG,
                           "test data: RX - ignore unexpect IP header");
                return;
        }
 
-       for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) {
+       for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) {
                if (*pos != (u8) i) {
                        wpa_printf(MSG_DEBUG,
                                   "test data: RX - ignore mismatching payload");
@@ -1890,8 +1894,8 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
        }
 
        extra[0] = '\0';
-       if (ntohs(ip.tot_len) != HWSIM_IP_LEN)
-               os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len));
+       if (ntohs(ip.ip_len) != HWSIM_IP_LEN)
+               os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len));
        wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s",
                MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra);
 }
@@ -1944,7 +1948,7 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
        u8 tos;
        u8 buf[2 + HWSIM_PACKETLEN];
        struct ether_header *eth;
-       struct iphdr *ip;
+       struct ip *ip;
        u8 *dpos;
        unsigned int i;
        size_t send_len = HWSIM_IP_LEN;
@@ -1983,17 +1987,17 @@ static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
        os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
        os_memcpy(eth->ether_shost, src, ETH_ALEN);
        eth->ether_type = htons(ETHERTYPE_IP);
-       ip = (struct iphdr *) (eth + 1);
+       ip = (struct ip *) (eth + 1);
        os_memset(ip, 0, sizeof(*ip));
-       ip->ihl = 5;
-       ip->version = 4;
-       ip->ttl = 64;
-       ip->tos = tos;
-       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));
+       ip->ip_hl = 5;
+       ip->ip_v = 4;
+       ip->ip_ttl = 64;
+       ip->ip_tos = tos;
+       ip->ip_len = htons(send_len);
+       ip->ip_p = 1;
+       ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
+       ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
+       ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip));
        dpos = (u8 *) (ip + 1);
        for (i = 0; i < send_len - sizeof(*ip); i++)
                *dpos++ = i;
@@ -2150,17 +2154,19 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
                if (hostapd_drv_set_key(hapd->conf->iface, hapd,
                                        hapd->last_igtk_alg,
                                        broadcast_ether_addr,
-                                       hapd->last_igtk_key_idx, 1, NULL, 0,
-                                       zero, hapd->last_igtk_len) < 0)
+                                       hapd->last_igtk_key_idx, 0, 1, NULL, 0,
+                                       zero, hapd->last_igtk_len,
+                                       KEY_FLAG_GROUP_TX_DEFAULT) < 0)
                        return -1;
 
                /* Set the previously configured key to reset its TSC */
                return hostapd_drv_set_key(hapd->conf->iface, hapd,
                                           hapd->last_igtk_alg,
                                           broadcast_ether_addr,
-                                          hapd->last_igtk_key_idx, 1, NULL, 0,
-                                          hapd->last_igtk,
-                                          hapd->last_igtk_len);
+                                          hapd->last_igtk_key_idx, 0, 1, NULL,
+                                          0, hapd->last_igtk,
+                                          hapd->last_igtk_len,
+                                          KEY_FLAG_GROUP_TX_DEFAULT);
        }
 
        if (is_broadcast_ether_addr(addr)) {
@@ -2174,16 +2180,19 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
                if (hostapd_drv_set_key(hapd->conf->iface, hapd,
                                        hapd->last_gtk_alg,
                                        broadcast_ether_addr,
-                                       hapd->last_gtk_key_idx, 1, NULL, 0,
-                                       zero, hapd->last_gtk_len) < 0)
+                                       hapd->last_gtk_key_idx, 0, 1, NULL, 0,
+                                       zero, hapd->last_gtk_len,
+                                       KEY_FLAG_GROUP_TX_DEFAULT) < 0)
                        return -1;
 
                /* Set the previously configured key to reset its TSC */
                return hostapd_drv_set_key(hapd->conf->iface, hapd,
                                           hapd->last_gtk_alg,
                                           broadcast_ether_addr,
-                                          hapd->last_gtk_key_idx, 1, NULL, 0,
-                                          hapd->last_gtk, hapd->last_gtk_len);
+                                          hapd->last_gtk_key_idx, 0, 1, NULL,
+                                          0, hapd->last_gtk,
+                                          hapd->last_gtk_len,
+                                          KEY_FLAG_GROUP_TX_DEFAULT);
        }
 
        sta = ap_get_sta(hapd, addr);
@@ -2199,14 +2208,16 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
        /* First, use a zero key to avoid any possible duplicate key avoidance
         * in the driver. */
        if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
-                               sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
-                               zero, sta->last_tk_len) < 0)
+                               sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
+                               zero, sta->last_tk_len,
+                               KEY_FLAG_PAIRWISE_RX_TX) < 0)
                return -1;
 
        /* Set the previously configured key to reset its TSC/RSC */
        return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
-                                  sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
-                                  sta->last_tk, sta->last_tk_len);
+                                  sta->addr, sta->last_tk_key_idx, 0, 1, NULL,
+                                  0, sta->last_tk, sta->last_tk_len,
+                                  KEY_FLAG_PAIRWISE_RX_TX);
 }
 
 
@@ -2215,11 +2226,12 @@ static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
        u8 addr[ETH_ALEN];
        const char *pos = cmd;
        enum wpa_alg alg;
+       enum key_flag key_flag;
        int idx, set_tx;
        u8 seq[6], key[WPA_TK_MAX_LEN];
        size_t key_len;
 
-       /* parameters: alg addr idx set_tx seq key */
+       /* parameters: alg addr idx set_tx seq key key_flag */
 
        alg = atoi(pos);
        pos = os_strchr(pos, ' ');
@@ -2248,13 +2260,24 @@ static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
        if (*pos != ' ')
                return -1;
        pos++;
-       key_len = os_strlen(pos) / 2;
+       if (!os_strchr(pos, ' '))
+               return -1;
+       key_len = (os_strchr(pos, ' ') - pos) / 2;
        if (hexstr2bin(pos, key, key_len) < 0)
                return -1;
+       pos += 2 * key_len;
+       if (*pos != ' ')
+               return -1;
+
+       pos++;
+       key_flag = atoi(pos);
+       pos = os_strchr(pos, ' ');
+       if (pos)
+               return -1;
 
        wpa_printf(MSG_INFO, "TESTING: Set key");
-       return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx,
-                                  set_tx, seq, 6, key, key_len);
+       return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx, 0,
+                                  set_tx, seq, 6, key, key_len, key_flag);
 }
 
 
@@ -2269,8 +2292,9 @@ static void restore_tk(void *ctx1, void *ctx2)
         * in replay protection issues for now since there is no clean way of
         * preventing encryption of a single EAPOL frame. */
        hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
-                           sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
-                           sta->last_tk, sta->last_tk_len);
+                           sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
+                           sta->last_tk, sta->last_tk_len,
+                           KEY_FLAG_PAIRWISE_RX_TX);
 }
 
 
@@ -2293,8 +2317,8 @@ static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
                wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
                           MAC2STR(sta->addr));
                hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
-                                   sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
-                                   NULL, 0);
+                                   sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
+                                   0, NULL, 0, KEY_FLAG_PAIRWISE);
        }
 
        wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
@@ -2323,8 +2347,8 @@ static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
                wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
                           MAC2STR(sta->addr));
                hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
-                                   sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
-                                   NULL, 0);
+                                   sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
+                                   0, NULL, 0, KEY_FLAG_PAIRWISE);
        }
 
        wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
@@ -2353,8 +2377,8 @@ static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
                wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
                           MAC2STR(sta->addr));
                hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
-                                   sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
-                                   NULL, 0);
+                                   sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
+                                   0, NULL, 0, KEY_FLAG_PAIRWISE);
        }
 
        wpa_printf(MSG_INFO,
@@ -2364,6 +2388,34 @@ static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
                                        plain ? restore_tk : NULL, hapd, sta);
 }
 
+
+static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
+                               char *buf, size_t buflen)
+{
+       struct sta_info *sta;
+       u8 addr[ETH_ALEN];
+       const u8 *pmk;
+       int pmk_len;
+
+       if (hwaddr_aton(cmd, addr))
+               return -1;
+
+       sta = ap_get_sta(hapd, addr);
+       if (!sta || !sta->wpa_sm) {
+               wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR,
+                          MAC2STR(addr));
+               return -1;
+       }
+       pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
+       if (!pmk) {
+               wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR,
+                          MAC2STR(addr));
+               return -1;
+       }
+
+       return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
+}
+
 #endif /* CONFIG_TESTING_OPTIONS */
 
 
@@ -2707,6 +2759,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;
@@ -2813,6 +2879,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;
 
@@ -2822,13 +2889,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);
 }
 
 
@@ -3214,6 +3284,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
        } else if (os_strcmp(buf, "REKEY_GTK") == 0) {
                if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0)
                        reply_len = -1;
+       } else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
+               reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
+                                                reply_size);
 #endif /* CONFIG_TESTING_OPTIONS */
        } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
                if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
@@ -3251,6 +3324,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;
@@ -3327,6 +3403,24 @@ 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_HANDOVER_REQ ", 21) == 0) {
+               res = hostapd_dpp_nfc_handover_req(hapd, buf + 20);
+               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_NFC_HANDOVER_SEL ", 21) == 0) {
+               res = hostapd_dpp_nfc_handover_sel(hapd, buf + 20);
+               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 = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
                if (res < 0) {
@@ -4595,13 +4689,8 @@ static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst,
                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);