New upstream snapshot.
Debian Janitor
2 years ago
36 | 36 | http://lists.infradead.org/mailman/listinfo/hostap |
37 | 37 | |
38 | 38 | The message should contain an inlined patch against the current |
39 | development branch (i.e., the master branch of | |
39 | development branch (i.e., the main branch of | |
40 | 40 | git://w1.fi/hostap.git). Please make sure the software you use for |
41 | 41 | sending the patch does not corrupt whitespace. If that cannot be fixed |
42 | 42 | for some reason, it is better to include an attached version of the |
0 | wpa (2:2.10+git20220401.1.c5d9f90-1) UNRELEASED; urgency=low | |
1 | ||
2 | * New upstream snapshot. | |
3 | ||
4 | -- Debian Janitor <janitor@jelmer.uk> Sat, 02 Apr 2022 14:24:39 -0000 | |
5 | ||
0 | 6 | wpa (2:2.10-3) unstable; urgency=medium |
1 | 7 | |
2 | 8 | [ Andrej Shadura ] |
115 | 115 | return 0; |
116 | 116 | } |
117 | 117 | #endif /* CONFIG_NO_VLAN */ |
118 | ||
119 | ||
120 | int hostapd_acl_comp(const void *a, const void *b) | |
121 | { | |
122 | const struct mac_acl_entry *aa = a; | |
123 | const struct mac_acl_entry *bb = b; | |
124 | return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); | |
125 | } | |
126 | ||
127 | ||
128 | int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, | |
129 | int vlan_id, const u8 *addr) | |
130 | { | |
131 | struct mac_acl_entry *newacl; | |
132 | ||
133 | newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); | |
134 | if (!newacl) { | |
135 | wpa_printf(MSG_ERROR, "MAC list reallocation failed"); | |
136 | return -1; | |
137 | } | |
138 | ||
139 | *acl = newacl; | |
140 | os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); | |
141 | os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id)); | |
142 | (*acl)[*num].vlan_id.untagged = vlan_id; | |
143 | (*acl)[*num].vlan_id.notempty = !!vlan_id; | |
144 | (*num)++; | |
145 | ||
146 | return 0; | |
147 | } | |
148 | ||
149 | ||
150 | void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, | |
151 | const u8 *addr) | |
152 | { | |
153 | int i = 0; | |
154 | ||
155 | while (i < *num) { | |
156 | if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) { | |
157 | os_remove_in_array(*acl, *num, sizeof(**acl), i); | |
158 | (*num)--; | |
159 | } else { | |
160 | i++; | |
161 | } | |
162 | } | |
163 | } | |
164 | 118 | |
165 | 119 | |
166 | 120 | static int hostapd_config_read_maclist(const char *fname, |
4660 | 4614 | return 1; |
4661 | 4615 | } |
4662 | 4616 | bss->mka_priority = mka_priority; |
4617 | } else if (os_strcmp(buf, "macsec_csindex") == 0) { | |
4618 | int macsec_csindex = atoi(pos); | |
4619 | ||
4620 | if (macsec_csindex < 0 || macsec_csindex > 1) { | |
4621 | wpa_printf(MSG_ERROR, | |
4622 | "Line %d: invalid macsec_csindex (%d): '%s'.", | |
4623 | line, macsec_csindex, pos); | |
4624 | return 1; | |
4625 | } | |
4626 | bss->macsec_csindex = macsec_csindex; | |
4663 | 4627 | } else if (os_strcmp(buf, "mka_cak") == 0) { |
4664 | 4628 | size_t len = os_strlen(pos); |
4665 | 4629 |
12 | 12 | int hostapd_set_iface(struct hostapd_config *conf, |
13 | 13 | struct hostapd_bss_config *bss, const char *field, |
14 | 14 | char *value); |
15 | int hostapd_acl_comp(const void *a, const void *b); | |
16 | int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, | |
17 | int vlan_id, const u8 *addr); | |
18 | void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, | |
19 | const u8 *addr); | |
20 | 15 | |
21 | 16 | #endif /* CONFIG_FILE_H */ |
771 | 771 | |
772 | 772 | #ifdef CONFIG_WNM_AP |
773 | 773 | |
774 | static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, | |
775 | const char *cmd) | |
776 | { | |
777 | u8 addr[ETH_ALEN]; | |
778 | int disassoc_timer; | |
779 | struct sta_info *sta; | |
780 | ||
781 | if (hwaddr_aton(cmd, addr)) | |
782 | return -1; | |
783 | if (cmd[17] != ' ') | |
784 | return -1; | |
785 | disassoc_timer = atoi(cmd + 17); | |
786 | ||
787 | sta = ap_get_sta(hapd, addr); | |
788 | if (sta == NULL) { | |
789 | wpa_printf(MSG_DEBUG, "Station " MACSTR | |
790 | " not found for disassociation imminent message", | |
791 | MAC2STR(addr)); | |
792 | return -1; | |
793 | } | |
794 | ||
795 | return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer); | |
796 | } | |
797 | ||
798 | ||
799 | static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, | |
800 | const char *cmd) | |
801 | { | |
802 | u8 addr[ETH_ALEN]; | |
803 | const char *url, *timerstr; | |
804 | int disassoc_timer; | |
805 | struct sta_info *sta; | |
806 | ||
807 | if (hwaddr_aton(cmd, addr)) | |
808 | return -1; | |
809 | ||
810 | sta = ap_get_sta(hapd, addr); | |
811 | if (sta == NULL) { | |
812 | wpa_printf(MSG_DEBUG, "Station " MACSTR | |
813 | " not found for ESS disassociation imminent message", | |
814 | MAC2STR(addr)); | |
815 | return -1; | |
816 | } | |
817 | ||
818 | timerstr = cmd + 17; | |
819 | if (*timerstr != ' ') | |
820 | return -1; | |
821 | timerstr++; | |
822 | disassoc_timer = atoi(timerstr); | |
823 | if (disassoc_timer < 0 || disassoc_timer > 65535) | |
824 | return -1; | |
825 | ||
826 | url = os_strchr(timerstr, ' '); | |
827 | if (url == NULL) | |
828 | return -1; | |
829 | url++; | |
830 | ||
831 | return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); | |
832 | } | |
833 | ||
834 | ||
835 | static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, | |
836 | const char *cmd) | |
837 | { | |
838 | u8 addr[ETH_ALEN]; | |
839 | const char *pos, *end; | |
840 | int disassoc_timer = 0; | |
841 | struct sta_info *sta; | |
842 | u8 req_mode = 0, valid_int = 0x01, dialog_token = 0x01; | |
843 | u8 bss_term_dur[12]; | |
844 | char *url = NULL; | |
845 | int ret; | |
846 | u8 nei_rep[1000]; | |
847 | int nei_len; | |
848 | u8 mbo[10]; | |
849 | size_t mbo_len = 0; | |
850 | ||
851 | if (hwaddr_aton(cmd, addr)) { | |
852 | wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); | |
853 | return -1; | |
854 | } | |
855 | ||
856 | sta = ap_get_sta(hapd, addr); | |
857 | if (sta == NULL) { | |
858 | wpa_printf(MSG_DEBUG, "Station " MACSTR | |
859 | " not found for BSS TM Request message", | |
860 | MAC2STR(addr)); | |
861 | return -1; | |
862 | } | |
863 | ||
864 | pos = os_strstr(cmd, " disassoc_timer="); | |
865 | if (pos) { | |
866 | pos += 16; | |
867 | disassoc_timer = atoi(pos); | |
868 | if (disassoc_timer < 0 || disassoc_timer > 65535) { | |
869 | wpa_printf(MSG_DEBUG, "Invalid disassoc_timer"); | |
870 | return -1; | |
871 | } | |
872 | } | |
873 | ||
874 | pos = os_strstr(cmd, " valid_int="); | |
875 | if (pos) { | |
876 | pos += 11; | |
877 | valid_int = atoi(pos); | |
878 | } | |
879 | ||
880 | pos = os_strstr(cmd, " dialog_token="); | |
881 | if (pos) { | |
882 | pos += 14; | |
883 | dialog_token = atoi(pos); | |
884 | } | |
885 | ||
886 | pos = os_strstr(cmd, " bss_term="); | |
887 | if (pos) { | |
888 | pos += 10; | |
889 | req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED; | |
890 | /* TODO: TSF configurable/learnable */ | |
891 | bss_term_dur[0] = 4; /* Subelement ID */ | |
892 | bss_term_dur[1] = 10; /* Length */ | |
893 | os_memset(&bss_term_dur[2], 0, 8); | |
894 | end = os_strchr(pos, ','); | |
895 | if (end == NULL) { | |
896 | wpa_printf(MSG_DEBUG, "Invalid bss_term data"); | |
897 | return -1; | |
898 | } | |
899 | end++; | |
900 | WPA_PUT_LE16(&bss_term_dur[10], atoi(end)); | |
901 | } | |
902 | ||
903 | nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep, | |
904 | sizeof(nei_rep)); | |
905 | if (nei_len < 0) | |
906 | return -1; | |
907 | ||
908 | pos = os_strstr(cmd, " url="); | |
909 | if (pos) { | |
910 | size_t len; | |
911 | pos += 5; | |
912 | end = os_strchr(pos, ' '); | |
913 | if (end) | |
914 | len = end - pos; | |
915 | else | |
916 | len = os_strlen(pos); | |
917 | url = os_malloc(len + 1); | |
918 | if (url == NULL) | |
919 | return -1; | |
920 | os_memcpy(url, pos, len); | |
921 | url[len] = '\0'; | |
922 | req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; | |
923 | } | |
924 | ||
925 | if (os_strstr(cmd, " pref=1")) | |
926 | req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; | |
927 | if (os_strstr(cmd, " abridged=1")) | |
928 | req_mode |= WNM_BSS_TM_REQ_ABRIDGED; | |
929 | if (os_strstr(cmd, " disassoc_imminent=1")) | |
930 | req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; | |
931 | ||
932 | #ifdef CONFIG_MBO | |
933 | pos = os_strstr(cmd, "mbo="); | |
934 | if (pos) { | |
935 | unsigned int mbo_reason, cell_pref, reassoc_delay; | |
936 | u8 *mbo_pos = mbo; | |
937 | ||
938 | ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason, | |
939 | &reassoc_delay, &cell_pref); | |
940 | if (ret != 3) { | |
941 | wpa_printf(MSG_DEBUG, | |
942 | "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>"); | |
943 | ret = -1; | |
944 | goto fail; | |
945 | } | |
946 | ||
947 | if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) { | |
948 | wpa_printf(MSG_DEBUG, | |
949 | "Invalid MBO transition reason code %u", | |
950 | mbo_reason); | |
951 | ret = -1; | |
952 | goto fail; | |
953 | } | |
954 | ||
955 | /* Valid values for Cellular preference are: 0, 1, 255 */ | |
956 | if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) { | |
957 | wpa_printf(MSG_DEBUG, | |
958 | "Invalid MBO cellular capability %u", | |
959 | cell_pref); | |
960 | ret = -1; | |
961 | goto fail; | |
962 | } | |
963 | ||
964 | if (reassoc_delay > 65535 || | |
965 | (reassoc_delay && | |
966 | !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) { | |
967 | wpa_printf(MSG_DEBUG, | |
968 | "MBO: Assoc retry delay is only valid in disassoc imminent mode"); | |
969 | ret = -1; | |
970 | goto fail; | |
971 | } | |
972 | ||
973 | *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON; | |
974 | *mbo_pos++ = 1; | |
975 | *mbo_pos++ = mbo_reason; | |
976 | *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF; | |
977 | *mbo_pos++ = 1; | |
978 | *mbo_pos++ = cell_pref; | |
979 | ||
980 | if (reassoc_delay) { | |
981 | *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY; | |
982 | *mbo_pos++ = 2; | |
983 | WPA_PUT_LE16(mbo_pos, reassoc_delay); | |
984 | mbo_pos += 2; | |
985 | } | |
986 | ||
987 | mbo_len = mbo_pos - mbo; | |
988 | } | |
989 | #endif /* CONFIG_MBO */ | |
990 | ||
991 | ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, | |
992 | valid_int, bss_term_dur, dialog_token, url, | |
993 | nei_len ? nei_rep : NULL, nei_len, | |
994 | mbo_len ? mbo : NULL, mbo_len); | |
995 | #ifdef CONFIG_MBO | |
996 | fail: | |
997 | #endif /* CONFIG_MBO */ | |
998 | os_free(url); | |
999 | return ret; | |
1000 | } | |
1001 | ||
1002 | ||
1003 | 774 | static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd, |
1004 | 775 | const char *cmd) |
1005 | 776 | { |
1358 | 1129 | } |
1359 | 1130 | |
1360 | 1131 | return pos - buf; |
1361 | } | |
1362 | ||
1363 | ||
1364 | static void hostapd_disassoc_accept_mac(struct hostapd_data *hapd) | |
1365 | { | |
1366 | struct sta_info *sta; | |
1367 | struct vlan_description vlan_id; | |
1368 | ||
1369 | if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED) | |
1370 | return; | |
1371 | ||
1372 | for (sta = hapd->sta_list; sta; sta = sta->next) { | |
1373 | if (!hostapd_maclist_found(hapd->conf->accept_mac, | |
1374 | hapd->conf->num_accept_mac, | |
1375 | sta->addr, &vlan_id) || | |
1376 | (vlan_id.notempty && | |
1377 | vlan_compare(&vlan_id, sta->vlan_desc))) | |
1378 | ap_sta_disconnect(hapd, sta, sta->addr, | |
1379 | WLAN_REASON_UNSPECIFIED); | |
1380 | } | |
1381 | } | |
1382 | ||
1383 | ||
1384 | static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd) | |
1385 | { | |
1386 | struct sta_info *sta; | |
1387 | struct vlan_description vlan_id; | |
1388 | ||
1389 | for (sta = hapd->sta_list; sta; sta = sta->next) { | |
1390 | if (hostapd_maclist_found(hapd->conf->deny_mac, | |
1391 | hapd->conf->num_deny_mac, sta->addr, | |
1392 | &vlan_id) && | |
1393 | (!vlan_id.notempty || | |
1394 | !vlan_compare(&vlan_id, sta->vlan_desc))) | |
1395 | ap_sta_disconnect(hapd, sta, sta->addr, | |
1396 | WLAN_REASON_UNSPECIFIED); | |
1397 | } | |
1398 | 1132 | } |
1399 | 1133 | |
1400 | 1134 | |
1518 | 1252 | } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { |
1519 | 1253 | os_free(hapd->dpp_configurator_params); |
1520 | 1254 | hapd->dpp_configurator_params = os_strdup(value); |
1255 | #ifdef CONFIG_DPP2 | |
1256 | dpp_controller_set_params(hapd->iface->interfaces->dpp, value); | |
1257 | #endif /* CONFIG_DPP2 */ | |
1521 | 1258 | } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) { |
1522 | 1259 | hapd->dpp_init_max_tries = atoi(value); |
1523 | 1260 | } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) { |
3378 | 3115 | } |
3379 | 3116 | |
3380 | 3117 | |
3381 | static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, | |
3382 | const char *txtaddr) | |
3383 | { | |
3384 | u8 addr[ETH_ALEN]; | |
3385 | struct vlan_description vlan_id; | |
3386 | ||
3387 | if (!(*num)) | |
3388 | return 0; | |
3389 | ||
3390 | if (hwaddr_aton(txtaddr, addr)) | |
3391 | return -1; | |
3392 | ||
3393 | if (hostapd_maclist_found(*acl, *num, addr, &vlan_id)) | |
3394 | hostapd_remove_acl_mac(acl, num, addr); | |
3395 | ||
3396 | return 0; | |
3397 | } | |
3398 | ||
3399 | ||
3400 | static void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, | |
3401 | int *num) | |
3402 | { | |
3403 | while (*num) | |
3404 | hostapd_remove_acl_mac(acl, num, (*acl)[0].addr); | |
3405 | } | |
3406 | ||
3407 | ||
3408 | static int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, | |
3409 | char *buf, size_t buflen) | |
3410 | { | |
3411 | int i = 0, len = 0, ret = 0; | |
3412 | ||
3413 | if (!acl) | |
3414 | return 0; | |
3415 | ||
3416 | while (i < num) { | |
3417 | ret = os_snprintf(buf + len, buflen - len, | |
3418 | MACSTR " VLAN_ID=%d\n", | |
3419 | MAC2STR(acl[i].addr), | |
3420 | acl[i].vlan_id.untagged); | |
3421 | if (ret < 0 || (size_t) ret >= buflen - len) | |
3422 | return len; | |
3423 | i++; | |
3424 | len += ret; | |
3425 | } | |
3426 | return len; | |
3427 | } | |
3428 | ||
3429 | ||
3430 | static int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, | |
3431 | const char *cmd) | |
3432 | { | |
3433 | u8 addr[ETH_ALEN]; | |
3434 | struct vlan_description vlan_id; | |
3435 | int ret = 0, vlanid = 0; | |
3436 | const char *pos; | |
3437 | ||
3438 | if (hwaddr_aton(cmd, addr)) | |
3439 | return -1; | |
3440 | ||
3441 | pos = os_strstr(cmd, "VLAN_ID="); | |
3442 | if (pos) | |
3443 | vlanid = atoi(pos + 8); | |
3444 | ||
3445 | if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) { | |
3446 | ret = hostapd_add_acl_maclist(acl, num, vlanid, addr); | |
3447 | if (ret != -1 && *acl) | |
3448 | qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); | |
3449 | } | |
3450 | ||
3451 | return ret < 0 ? -1 : 0; | |
3452 | } | |
3453 | ||
3454 | ||
3455 | 3118 | static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd, |
3456 | 3119 | const char *field, char *buf, |
3457 | 3120 | size_t buflen) |
3827 | 3490 | if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { |
3828 | 3491 | if (hostapd_ctrl_iface_acl_add_mac( |
3829 | 3492 | &hapd->conf->accept_mac, |
3830 | &hapd->conf->num_accept_mac, buf + 19)) | |
3493 | &hapd->conf->num_accept_mac, buf + 19) || | |
3494 | hostapd_set_acl(hapd)) | |
3831 | 3495 | reply_len = -1; |
3832 | 3496 | } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { |
3833 | if (!hostapd_ctrl_iface_acl_del_mac( | |
3497 | if (hostapd_ctrl_iface_acl_del_mac( | |
3834 | 3498 | &hapd->conf->accept_mac, |
3835 | &hapd->conf->num_accept_mac, buf + 19)) | |
3836 | hostapd_disassoc_accept_mac(hapd); | |
3837 | else | |
3499 | &hapd->conf->num_accept_mac, buf + 19) || | |
3500 | hostapd_set_acl(hapd) || | |
3501 | hostapd_disassoc_accept_mac(hapd)) | |
3838 | 3502 | reply_len = -1; |
3839 | 3503 | } else if (os_strcmp(buf + 11, "SHOW") == 0) { |
3840 | 3504 | reply_len = hostapd_ctrl_iface_acl_show_mac( |
3844 | 3508 | hostapd_ctrl_iface_acl_clear_list( |
3845 | 3509 | &hapd->conf->accept_mac, |
3846 | 3510 | &hapd->conf->num_accept_mac); |
3847 | hostapd_disassoc_accept_mac(hapd); | |
3511 | if (hostapd_set_acl(hapd) || | |
3512 | hostapd_disassoc_accept_mac(hapd)) | |
3513 | reply_len = -1; | |
3848 | 3514 | } |
3849 | 3515 | } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { |
3850 | 3516 | if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { |
3851 | if (!hostapd_ctrl_iface_acl_add_mac( | |
3517 | if (hostapd_ctrl_iface_acl_add_mac( | |
3852 | 3518 | &hapd->conf->deny_mac, |
3853 | &hapd->conf->num_deny_mac, buf + 17)) | |
3854 | hostapd_disassoc_deny_mac(hapd); | |
3855 | else | |
3519 | &hapd->conf->num_deny_mac, buf + 17) || | |
3520 | hostapd_set_acl(hapd) || | |
3521 | hostapd_disassoc_deny_mac(hapd)) | |
3856 | 3522 | reply_len = -1; |
3857 | 3523 | } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { |
3858 | 3524 | if (hostapd_ctrl_iface_acl_del_mac( |
3859 | 3525 | &hapd->conf->deny_mac, |
3860 | &hapd->conf->num_deny_mac, buf + 17)) | |
3526 | &hapd->conf->num_deny_mac, buf + 17) || | |
3527 | hostapd_set_acl(hapd)) | |
3861 | 3528 | reply_len = -1; |
3862 | 3529 | } else if (os_strcmp(buf + 9, "SHOW") == 0) { |
3863 | 3530 | reply_len = hostapd_ctrl_iface_acl_show_mac( |
3867 | 3534 | hostapd_ctrl_iface_acl_clear_list( |
3868 | 3535 | &hapd->conf->deny_mac, |
3869 | 3536 | &hapd->conf->num_deny_mac); |
3537 | if (hostapd_set_acl(hapd)) | |
3538 | reply_len = -1; | |
3870 | 3539 | } |
3871 | 3540 | #ifdef CONFIG_DPP |
3872 | 3541 | } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { |
3958 | 3627 | if (os_snprintf_error(reply_size, reply_len)) |
3959 | 3628 | reply_len = -1; |
3960 | 3629 | } |
3630 | } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) { | |
3631 | if (dpp_configurator_set(hapd->iface->interfaces->dpp, | |
3632 | buf + 20) < 0) | |
3633 | reply_len = -1; | |
3961 | 3634 | } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { |
3962 | 3635 | if (dpp_configurator_remove(hapd->iface->interfaces->dpp, |
3963 | 3636 | buf + 24) < 0) |
1069 | 1069 | # mka_priority (Priority of MKA Actor) |
1070 | 1070 | # Range: 0..255 (default: 255) |
1071 | 1071 | # |
1072 | # macsec_csindex: IEEE 802.1X/MACsec cipher suite | |
1073 | # 0 = GCM-AES-128 (default) | |
1074 | # 1 = GCM-AES-256 (default) | |
1075 | # | |
1072 | 1076 | # mka_cak, mka_ckn, and mka_priority: IEEE 802.1X/MACsec pre-shared key mode |
1073 | 1077 | # This allows to configure MACsec with a pre-shared key using a (CAK,CKN) pair. |
1074 | 1078 | # In this mode, instances of hostapd can act as MACsec peers. The peer |
722 | 722 | case 'v': |
723 | 723 | show_version(); |
724 | 724 | exit(1); |
725 | break; | |
726 | 725 | case 'g': |
727 | 726 | if (hostapd_get_global_ctrl_iface(&interfaces, optarg)) |
728 | 727 | return -1; |
59 | 59 | |
60 | 60 | L_CFLAGS += -Wno-unused-parameter |
61 | 61 | |
62 | ifneq ($(TARGET_BUILD_VARIANT), user) | |
63 | ifeq ($(shell test $(PLATFORM_VERSION_LAST_STABLE) -ge 8 ; echo $$?), 0) | |
64 | L_CFLAGS += -DCONFIG_ANDROID_LOG | |
65 | L_CFLAGS += -DANDROID_LOG_NAME='"hs20-osu-client"' | |
66 | L_CFLAGS += -Wno-error-deprecated-declarations | |
67 | L_CFLAGS += -Wno-unused-variable | |
68 | endif | |
69 | endif | |
62 | 70 | |
63 | 71 | ######################## |
64 | 72 | include $(CLEAR_VARS) |
67 | 75 | |
68 | 76 | LOCAL_SHARED_LIBRARIES := libc libcutils |
69 | 77 | LOCAL_SHARED_LIBRARIES += libcrypto libssl |
78 | ifneq ($(TARGET_BUILD_VARIANT), user) | |
79 | ifeq ($(shell test $(PLATFORM_VERSION_LAST_STABLE) -ge 8 ; echo $$?), 0) | |
80 | LOCAL_VENDOR_MODULE := true | |
81 | LOCAL_SHARED_LIBRARIES += libxml2 | |
82 | LOCAL_SHARED_LIBRARIES += liblog | |
83 | else | |
70 | 84 | #LOCAL_SHARED_LIBRARIES += libxml2 |
71 | 85 | LOCAL_STATIC_LIBRARIES += libxml2 |
72 | 86 | LOCAL_SHARED_LIBRARIES += libicuuc |
87 | endif | |
88 | endif | |
73 | 89 | LOCAL_SHARED_LIBRARIES += libcurl |
74 | 90 | |
75 | 91 | LOCAL_CFLAGS := $(L_CFLAGS) |
9 | 9 | #include <time.h> |
10 | 10 | #include <sys/stat.h> |
11 | 11 | #ifdef ANDROID |
12 | #include "private/android_filesystem_config.h" | |
12 | #include "cutils/android_filesystem_config.h" | |
13 | 13 | #endif /* ANDROID */ |
14 | 14 | |
15 | 15 | #include "common.h" |
2910 | 2910 | int found; |
2911 | 2911 | char *host = NULL; |
2912 | 2912 | |
2913 | wpa_printf(MSG_INFO, "osu_cert_cb(osu_cert_validation=%d, url=%s)", | |
2914 | !ctx->no_osu_cert_validation, ctx->server_url); | |
2915 | ||
2916 | host = get_hostname(ctx->server_url); | |
2917 | ||
2918 | for (i = 0; i < ctx->server_dnsname_count; i++) | |
2919 | os_free(ctx->server_dnsname[i]); | |
2920 | os_free(ctx->server_dnsname); | |
2921 | ctx->server_dnsname = os_calloc(cert->num_dnsname, sizeof(char *)); | |
2922 | ctx->server_dnsname_count = 0; | |
2913 | wpa_printf(MSG_INFO, "osu_cert_cb(osu_cert_validation=%d, url=%s server_url=%s)", | |
2914 | !ctx->no_osu_cert_validation, cert->url ? cert->url : "N/A", | |
2915 | ctx->server_url); | |
2916 | ||
2917 | if (ctx->no_osu_cert_validation && cert->url) | |
2918 | host = get_hostname(cert->url); | |
2919 | else | |
2920 | host = get_hostname(ctx->server_url); | |
2921 | ||
2922 | if (!ctx->no_osu_cert_validation) { | |
2923 | for (i = 0; i < ctx->server_dnsname_count; i++) | |
2924 | os_free(ctx->server_dnsname[i]); | |
2925 | os_free(ctx->server_dnsname); | |
2926 | ctx->server_dnsname = os_calloc(cert->num_dnsname, | |
2927 | sizeof(char *)); | |
2928 | ctx->server_dnsname_count = 0; | |
2929 | } | |
2923 | 2930 | |
2924 | 2931 | found = 0; |
2925 | 2932 | for (i = 0; i < cert->num_dnsname; i++) { |
2926 | if (ctx->server_dnsname) { | |
2933 | if (!ctx->no_osu_cert_validation && ctx->server_dnsname) { | |
2927 | 2934 | ctx->server_dnsname[ctx->server_dnsname_count] = |
2928 | 2935 | os_strdup(cert->dnsname[i]); |
2929 | 2936 | if (ctx->server_dnsname[ctx->server_dnsname_count]) |
3248 | 3255 | default: |
3249 | 3256 | usage(); |
3250 | 3257 | exit(0); |
3251 | break; | |
3252 | 3258 | } |
3253 | 3259 | } |
3254 | 3260 |
563 | 563 | free(id); |
564 | 564 | return -1; |
565 | 565 | } |
566 | return 0; | |
567 | 566 | } |
568 | 567 | |
569 | 568 | if (strcasecmp(name, "uploadMO") == 0) { |
1384 | 1384 | SUBSCRIPTION_REGISTRATION, mac_addr) < 0) |
1385 | 1385 | return NULL; |
1386 | 1386 | val = db_get_osu_config_val(ctx, realm, "signup_url"); |
1387 | if (val == NULL) | |
1388 | return NULL; | |
1387 | if (!val) { | |
1388 | hs20_eventlog(ctx, NULL, realm, session_id, | |
1389 | "signup_url not configured in osu_config", NULL); | |
1390 | return NULL; | |
1391 | } | |
1389 | 1392 | |
1390 | 1393 | spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", |
1391 | 1394 | NULL); |
1645 | 1645 | return with_pk; |
1646 | 1646 | } |
1647 | 1647 | #endif /* CONFIG_SAE_PK */ |
1648 | ||
1649 | ||
1650 | int hostapd_acl_comp(const void *a, const void *b) | |
1651 | { | |
1652 | const struct mac_acl_entry *aa = a; | |
1653 | const struct mac_acl_entry *bb = b; | |
1654 | return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); | |
1655 | } | |
1656 | ||
1657 | ||
1658 | int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, | |
1659 | int vlan_id, const u8 *addr) | |
1660 | { | |
1661 | struct mac_acl_entry *newacl; | |
1662 | ||
1663 | newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl)); | |
1664 | if (!newacl) { | |
1665 | wpa_printf(MSG_ERROR, "MAC list reallocation failed"); | |
1666 | return -1; | |
1667 | } | |
1668 | ||
1669 | *acl = newacl; | |
1670 | os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); | |
1671 | os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id)); | |
1672 | (*acl)[*num].vlan_id.untagged = vlan_id; | |
1673 | (*acl)[*num].vlan_id.notempty = !!vlan_id; | |
1674 | (*num)++; | |
1675 | ||
1676 | return 0; | |
1677 | } | |
1678 | ||
1679 | ||
1680 | void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, | |
1681 | const u8 *addr) | |
1682 | { | |
1683 | int i = 0; | |
1684 | ||
1685 | while (i < *num) { | |
1686 | if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) { | |
1687 | os_remove_in_array(*acl, *num, sizeof(**acl), i); | |
1688 | (*num)--; | |
1689 | } else { | |
1690 | i++; | |
1691 | } | |
1692 | } | |
1693 | } |
848 | 848 | int mka_priority; |
849 | 849 | |
850 | 850 | /** |
851 | * macsec_csindex - Cipher suite index for MACsec | |
852 | * | |
853 | * Range: 0-1 (default: 0) | |
854 | */ | |
855 | int macsec_csindex; | |
856 | ||
857 | /** | |
851 | 858 | * mka_ckn - MKA pre-shared CKN |
852 | 859 | */ |
853 | 860 | #define MACSEC_CKN_MAX_LEN 32 |
1194 | 1201 | bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf); |
1195 | 1202 | bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf); |
1196 | 1203 | int hostapd_setup_sae_pt(struct hostapd_bss_config *conf); |
1204 | int hostapd_acl_comp(const void *a, const void *b); | |
1205 | int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num, | |
1206 | int vlan_id, const u8 *addr); | |
1207 | void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num, | |
1208 | const u8 *addr); | |
1197 | 1209 | |
1198 | 1210 | #endif /* HOSTAPD_CONFIG_H */ |
811 | 811 | int channel, int ht_enabled, int vht_enabled, |
812 | 812 | int he_enabled, |
813 | 813 | int sec_channel_offset, int oper_chwidth, |
814 | int center_segment0, int center_segment1) | |
814 | int center_segment0, int center_segment1, | |
815 | bool radar_background) | |
815 | 816 | { |
816 | 817 | struct hostapd_data *hapd = iface->bss[0]; |
817 | 818 | struct hostapd_freq_params data; |
837 | 838 | wpa_printf(MSG_ERROR, "Can't set freq params"); |
838 | 839 | return -1; |
839 | 840 | } |
841 | data.radar_background = radar_background; | |
840 | 842 | |
841 | 843 | res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); |
842 | 844 | if (!res) { |
843 | iface->cac_started = 1; | |
845 | if (radar_background) | |
846 | iface->radar_background.cac_started = 1; | |
847 | else | |
848 | iface->cac_started = 1; | |
844 | 849 | os_get_reltime(&iface->dfs_cac_start); |
845 | 850 | } |
846 | 851 |
129 | 129 | int channel, int ht_enabled, int vht_enabled, |
130 | 130 | int he_enabled, |
131 | 131 | int sec_channel_offset, int oper_chwidth, |
132 | int center_segment0, int center_segment1); | |
132 | int center_segment0, int center_segment1, | |
133 | bool radar_background); | |
133 | 134 | int hostapd_drv_do_acs(struct hostapd_data *hapd); |
134 | 135 | int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer, |
135 | 136 | u16 reason_code, const u8 *ie, size_t ielen); |
23 | 23 | #include "ap_drv_ops.h" |
24 | 24 | #include "mbo_ap.h" |
25 | 25 | #include "taxonomy.h" |
26 | #include "wnm_ap.h" | |
26 | 27 | |
27 | 28 | |
28 | 29 | static size_t hostapd_write_ht_mcs_bitmask(char *buf, size_t buflen, |
723 | 724 | } else { |
724 | 725 | /* CAC started and CAC time set - calculate remaining time */ |
725 | 726 | struct os_reltime now; |
726 | unsigned int left_time; | |
727 | long left_time; | |
727 | 728 | |
728 | 729 | os_reltime_age(&iface->dfs_cac_start, &now); |
729 | left_time = iface->dfs_cac_ms / 1000 - now.sec; | |
730 | left_time = (long) iface->dfs_cac_ms / 1000 - now.sec; | |
730 | 731 | ret = os_snprintf(buf + len, buflen - len, |
731 | 732 | "cac_time_seconds=%u\n" |
732 | "cac_time_left_seconds=%u\n", | |
733 | "cac_time_left_seconds=%lu\n", | |
733 | 734 | iface->dfs_cac_ms / 1000, |
734 | left_time); | |
735 | left_time > 0 ? left_time : 0); | |
735 | 736 | } |
736 | 737 | if (os_snprintf_error(buflen - len, ret)) |
737 | 738 | return len; |
1046 | 1047 | |
1047 | 1048 | #endif /* CONFIG_MESH */ |
1048 | 1049 | #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ |
1050 | ||
1051 | ||
1052 | #ifdef CONFIG_WNM_AP | |
1053 | ||
1054 | int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, | |
1055 | const char *cmd) | |
1056 | { | |
1057 | u8 addr[ETH_ALEN]; | |
1058 | int disassoc_timer; | |
1059 | struct sta_info *sta; | |
1060 | ||
1061 | if (hwaddr_aton(cmd, addr)) | |
1062 | return -1; | |
1063 | if (cmd[17] != ' ') | |
1064 | return -1; | |
1065 | disassoc_timer = atoi(cmd + 17); | |
1066 | ||
1067 | sta = ap_get_sta(hapd, addr); | |
1068 | if (sta == NULL) { | |
1069 | wpa_printf(MSG_DEBUG, "Station " MACSTR | |
1070 | " not found for disassociation imminent message", | |
1071 | MAC2STR(addr)); | |
1072 | return -1; | |
1073 | } | |
1074 | ||
1075 | return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer); | |
1076 | } | |
1077 | ||
1078 | ||
1079 | int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, | |
1080 | const char *cmd) | |
1081 | { | |
1082 | u8 addr[ETH_ALEN]; | |
1083 | const char *url, *timerstr; | |
1084 | int disassoc_timer; | |
1085 | struct sta_info *sta; | |
1086 | ||
1087 | if (hwaddr_aton(cmd, addr)) | |
1088 | return -1; | |
1089 | ||
1090 | sta = ap_get_sta(hapd, addr); | |
1091 | if (sta == NULL) { | |
1092 | wpa_printf(MSG_DEBUG, "Station " MACSTR | |
1093 | " not found for ESS disassociation imminent message", | |
1094 | MAC2STR(addr)); | |
1095 | return -1; | |
1096 | } | |
1097 | ||
1098 | timerstr = cmd + 17; | |
1099 | if (*timerstr != ' ') | |
1100 | return -1; | |
1101 | timerstr++; | |
1102 | disassoc_timer = atoi(timerstr); | |
1103 | if (disassoc_timer < 0 || disassoc_timer > 65535) | |
1104 | return -1; | |
1105 | ||
1106 | url = os_strchr(timerstr, ' '); | |
1107 | if (url == NULL) | |
1108 | return -1; | |
1109 | url++; | |
1110 | ||
1111 | return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); | |
1112 | } | |
1113 | ||
1114 | ||
1115 | int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, | |
1116 | const char *cmd) | |
1117 | { | |
1118 | u8 addr[ETH_ALEN]; | |
1119 | const char *pos, *end; | |
1120 | int disassoc_timer = 0; | |
1121 | struct sta_info *sta; | |
1122 | u8 req_mode = 0, valid_int = 0x01, dialog_token = 0x01; | |
1123 | u8 bss_term_dur[12]; | |
1124 | char *url = NULL; | |
1125 | int ret; | |
1126 | u8 nei_rep[1000]; | |
1127 | int nei_len; | |
1128 | u8 mbo[10]; | |
1129 | size_t mbo_len = 0; | |
1130 | ||
1131 | if (hwaddr_aton(cmd, addr)) { | |
1132 | wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); | |
1133 | return -1; | |
1134 | } | |
1135 | ||
1136 | sta = ap_get_sta(hapd, addr); | |
1137 | if (sta == NULL) { | |
1138 | wpa_printf(MSG_DEBUG, "Station " MACSTR | |
1139 | " not found for BSS TM Request message", | |
1140 | MAC2STR(addr)); | |
1141 | return -1; | |
1142 | } | |
1143 | ||
1144 | pos = os_strstr(cmd, " disassoc_timer="); | |
1145 | if (pos) { | |
1146 | pos += 16; | |
1147 | disassoc_timer = atoi(pos); | |
1148 | if (disassoc_timer < 0 || disassoc_timer > 65535) { | |
1149 | wpa_printf(MSG_DEBUG, "Invalid disassoc_timer"); | |
1150 | return -1; | |
1151 | } | |
1152 | } | |
1153 | ||
1154 | pos = os_strstr(cmd, " valid_int="); | |
1155 | if (pos) { | |
1156 | pos += 11; | |
1157 | valid_int = atoi(pos); | |
1158 | } | |
1159 | ||
1160 | pos = os_strstr(cmd, " dialog_token="); | |
1161 | if (pos) { | |
1162 | pos += 14; | |
1163 | dialog_token = atoi(pos); | |
1164 | } | |
1165 | ||
1166 | pos = os_strstr(cmd, " bss_term="); | |
1167 | if (pos) { | |
1168 | pos += 10; | |
1169 | req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED; | |
1170 | /* TODO: TSF configurable/learnable */ | |
1171 | bss_term_dur[0] = 4; /* Subelement ID */ | |
1172 | bss_term_dur[1] = 10; /* Length */ | |
1173 | os_memset(&bss_term_dur[2], 0, 8); | |
1174 | end = os_strchr(pos, ','); | |
1175 | if (end == NULL) { | |
1176 | wpa_printf(MSG_DEBUG, "Invalid bss_term data"); | |
1177 | return -1; | |
1178 | } | |
1179 | end++; | |
1180 | WPA_PUT_LE16(&bss_term_dur[10], atoi(end)); | |
1181 | } | |
1182 | ||
1183 | nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep, | |
1184 | sizeof(nei_rep)); | |
1185 | if (nei_len < 0) | |
1186 | return -1; | |
1187 | ||
1188 | pos = os_strstr(cmd, " url="); | |
1189 | if (pos) { | |
1190 | size_t len; | |
1191 | pos += 5; | |
1192 | end = os_strchr(pos, ' '); | |
1193 | if (end) | |
1194 | len = end - pos; | |
1195 | else | |
1196 | len = os_strlen(pos); | |
1197 | url = os_malloc(len + 1); | |
1198 | if (url == NULL) | |
1199 | return -1; | |
1200 | os_memcpy(url, pos, len); | |
1201 | url[len] = '\0'; | |
1202 | req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; | |
1203 | } | |
1204 | ||
1205 | if (os_strstr(cmd, " pref=1")) | |
1206 | req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; | |
1207 | if (os_strstr(cmd, " abridged=1")) | |
1208 | req_mode |= WNM_BSS_TM_REQ_ABRIDGED; | |
1209 | if (os_strstr(cmd, " disassoc_imminent=1")) | |
1210 | req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; | |
1211 | ||
1212 | #ifdef CONFIG_MBO | |
1213 | pos = os_strstr(cmd, "mbo="); | |
1214 | if (pos) { | |
1215 | unsigned int mbo_reason, cell_pref, reassoc_delay; | |
1216 | u8 *mbo_pos = mbo; | |
1217 | ||
1218 | ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason, | |
1219 | &reassoc_delay, &cell_pref); | |
1220 | if (ret != 3) { | |
1221 | wpa_printf(MSG_DEBUG, | |
1222 | "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>"); | |
1223 | ret = -1; | |
1224 | goto fail; | |
1225 | } | |
1226 | ||
1227 | if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) { | |
1228 | wpa_printf(MSG_DEBUG, | |
1229 | "Invalid MBO transition reason code %u", | |
1230 | mbo_reason); | |
1231 | ret = -1; | |
1232 | goto fail; | |
1233 | } | |
1234 | ||
1235 | /* Valid values for Cellular preference are: 0, 1, 255 */ | |
1236 | if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) { | |
1237 | wpa_printf(MSG_DEBUG, | |
1238 | "Invalid MBO cellular capability %u", | |
1239 | cell_pref); | |
1240 | ret = -1; | |
1241 | goto fail; | |
1242 | } | |
1243 | ||
1244 | if (reassoc_delay > 65535 || | |
1245 | (reassoc_delay && | |
1246 | !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) { | |
1247 | wpa_printf(MSG_DEBUG, | |
1248 | "MBO: Assoc retry delay is only valid in disassoc imminent mode"); | |
1249 | ret = -1; | |
1250 | goto fail; | |
1251 | } | |
1252 | ||
1253 | *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON; | |
1254 | *mbo_pos++ = 1; | |
1255 | *mbo_pos++ = mbo_reason; | |
1256 | *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF; | |
1257 | *mbo_pos++ = 1; | |
1258 | *mbo_pos++ = cell_pref; | |
1259 | ||
1260 | if (reassoc_delay) { | |
1261 | *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY; | |
1262 | *mbo_pos++ = 2; | |
1263 | WPA_PUT_LE16(mbo_pos, reassoc_delay); | |
1264 | mbo_pos += 2; | |
1265 | } | |
1266 | ||
1267 | mbo_len = mbo_pos - mbo; | |
1268 | } | |
1269 | #endif /* CONFIG_MBO */ | |
1270 | ||
1271 | ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, | |
1272 | valid_int, bss_term_dur, dialog_token, url, | |
1273 | nei_len ? nei_rep : NULL, nei_len, | |
1274 | mbo_len ? mbo : NULL, mbo_len); | |
1275 | #ifdef CONFIG_MBO | |
1276 | fail: | |
1277 | #endif /* CONFIG_MBO */ | |
1278 | os_free(url); | |
1279 | return ret; | |
1280 | } | |
1281 | ||
1282 | #endif /* CONFIG_WNM_AP */ | |
1283 | ||
1284 | ||
1285 | int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, | |
1286 | const char *txtaddr) | |
1287 | { | |
1288 | u8 addr[ETH_ALEN]; | |
1289 | struct vlan_description vlan_id; | |
1290 | ||
1291 | if (!(*num)) | |
1292 | return 0; | |
1293 | ||
1294 | if (hwaddr_aton(txtaddr, addr)) | |
1295 | return -1; | |
1296 | ||
1297 | if (hostapd_maclist_found(*acl, *num, addr, &vlan_id)) | |
1298 | hostapd_remove_acl_mac(acl, num, addr); | |
1299 | ||
1300 | return 0; | |
1301 | } | |
1302 | ||
1303 | ||
1304 | void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, | |
1305 | int *num) | |
1306 | { | |
1307 | while (*num) | |
1308 | hostapd_remove_acl_mac(acl, num, (*acl)[0].addr); | |
1309 | } | |
1310 | ||
1311 | ||
1312 | int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, | |
1313 | char *buf, size_t buflen) | |
1314 | { | |
1315 | int i = 0, len = 0, ret = 0; | |
1316 | ||
1317 | if (!acl) | |
1318 | return 0; | |
1319 | ||
1320 | while (i < num) { | |
1321 | ret = os_snprintf(buf + len, buflen - len, | |
1322 | MACSTR " VLAN_ID=%d\n", | |
1323 | MAC2STR(acl[i].addr), | |
1324 | acl[i].vlan_id.untagged); | |
1325 | if (ret < 0 || (size_t) ret >= buflen - len) | |
1326 | return len; | |
1327 | i++; | |
1328 | len += ret; | |
1329 | } | |
1330 | return len; | |
1331 | } | |
1332 | ||
1333 | ||
1334 | int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, | |
1335 | const char *cmd) | |
1336 | { | |
1337 | u8 addr[ETH_ALEN]; | |
1338 | struct vlan_description vlan_id; | |
1339 | int ret = 0, vlanid = 0; | |
1340 | const char *pos; | |
1341 | ||
1342 | if (hwaddr_aton(cmd, addr)) | |
1343 | return -1; | |
1344 | ||
1345 | pos = os_strstr(cmd, "VLAN_ID="); | |
1346 | if (pos) | |
1347 | vlanid = atoi(pos + 8); | |
1348 | ||
1349 | if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) { | |
1350 | ret = hostapd_add_acl_maclist(acl, num, vlanid, addr); | |
1351 | if (ret != -1 && *acl) | |
1352 | qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); | |
1353 | } | |
1354 | ||
1355 | return ret < 0 ? -1 : 0; | |
1356 | } | |
1357 | ||
1358 | ||
1359 | int hostapd_disassoc_accept_mac(struct hostapd_data *hapd) | |
1360 | { | |
1361 | struct sta_info *sta; | |
1362 | struct vlan_description vlan_id; | |
1363 | ||
1364 | if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED) | |
1365 | return 0; | |
1366 | ||
1367 | for (sta = hapd->sta_list; sta; sta = sta->next) { | |
1368 | if (!hostapd_maclist_found(hapd->conf->accept_mac, | |
1369 | hapd->conf->num_accept_mac, | |
1370 | sta->addr, &vlan_id) || | |
1371 | (vlan_id.notempty && | |
1372 | vlan_compare(&vlan_id, sta->vlan_desc))) | |
1373 | ap_sta_disconnect(hapd, sta, sta->addr, | |
1374 | WLAN_REASON_UNSPECIFIED); | |
1375 | } | |
1376 | ||
1377 | return 0; | |
1378 | } | |
1379 | ||
1380 | ||
1381 | int hostapd_disassoc_deny_mac(struct hostapd_data *hapd) | |
1382 | { | |
1383 | struct sta_info *sta; | |
1384 | struct vlan_description vlan_id; | |
1385 | ||
1386 | for (sta = hapd->sta_list; sta; sta = sta->next) { | |
1387 | if (hostapd_maclist_found(hapd->conf->deny_mac, | |
1388 | hapd->conf->num_deny_mac, sta->addr, | |
1389 | &vlan_id) && | |
1390 | (!vlan_id.notempty || | |
1391 | !vlan_compare(&vlan_id, sta->vlan_desc))) | |
1392 | ap_sta_disconnect(hapd, sta, sta->addr, | |
1393 | WLAN_REASON_UNSPECIFIED); | |
1394 | } | |
1395 | ||
1396 | return 0; | |
1397 | } |
36 | 36 | const u8 *addr, char *buf, size_t len); |
37 | 37 | void * hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd); |
38 | 38 | |
39 | int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, | |
40 | const char *cmd); | |
41 | int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, | |
42 | const char *cmd); | |
43 | int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, | |
44 | const char *cmd); | |
45 | int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num, | |
46 | const char *cmd); | |
47 | int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, | |
48 | const char *txtaddr); | |
49 | void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl, | |
50 | int *num); | |
51 | int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num, | |
52 | char *buf, size_t buflen); | |
53 | int hostapd_disassoc_accept_mac(struct hostapd_data *hapd); | |
54 | int hostapd_disassoc_deny_mac(struct hostapd_data *hapd); | |
55 | ||
39 | 56 | #endif /* CTRL_IFACE_AP_H */ |
16 | 16 | #include "ap_drv_ops.h" |
17 | 17 | #include "drivers/driver.h" |
18 | 18 | #include "dfs.h" |
19 | ||
20 | ||
21 | enum dfs_channel_type { | |
22 | DFS_ANY_CHANNEL, | |
23 | DFS_AVAILABLE, /* non-radar or radar-available */ | |
24 | DFS_NO_CAC_YET, /* radar-not-yet-available */ | |
25 | }; | |
26 | ||
27 | static struct hostapd_channel_data * | |
28 | dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, | |
29 | u8 *oper_centr_freq_seg0_idx, | |
30 | u8 *oper_centr_freq_seg1_idx, | |
31 | enum dfs_channel_type *channel_type); | |
32 | ||
33 | ||
34 | static bool dfs_use_radar_background(struct hostapd_iface *iface) | |
35 | { | |
36 | return iface->drv_flags2 & WPA_DRIVER_RADAR_BACKGROUND; | |
37 | } | |
19 | 38 | |
20 | 39 | |
21 | 40 | static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) |
50 | 69 | } |
51 | 70 | |
52 | 71 | |
72 | /* dfs_channel_available: select new channel according to type parameter */ | |
53 | 73 | static int dfs_channel_available(struct hostapd_channel_data *chan, |
54 | int skip_radar) | |
55 | { | |
74 | enum dfs_channel_type type) | |
75 | { | |
76 | if (type == DFS_NO_CAC_YET) { | |
77 | /* Select only radar channel where CAC has not been | |
78 | * performed yet | |
79 | */ | |
80 | if ((chan->flag & HOSTAPD_CHAN_RADAR) && | |
81 | (chan->flag & HOSTAPD_CHAN_DFS_MASK) == | |
82 | HOSTAPD_CHAN_DFS_USABLE) | |
83 | return 1; | |
84 | return 0; | |
85 | } | |
86 | ||
56 | 87 | /* |
57 | 88 | * When radar detection happens, CSA is performed. However, there's no |
58 | 89 | * time for CAC, so radar channels must be skipped when finding a new |
59 | 90 | * channel for CSA, unless they are available for immediate use. |
60 | 91 | */ |
61 | if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) && | |
92 | if (type == DFS_AVAILABLE && (chan->flag & HOSTAPD_CHAN_RADAR) && | |
62 | 93 | ((chan->flag & HOSTAPD_CHAN_DFS_MASK) != |
63 | 94 | HOSTAPD_CHAN_DFS_AVAILABLE)) |
64 | 95 | return 0; |
137 | 168 | |
138 | 169 | static int dfs_chan_range_available(struct hostapd_hw_modes *mode, |
139 | 170 | int first_chan_idx, int num_chans, |
140 | int skip_radar) | |
171 | enum dfs_channel_type type) | |
141 | 172 | { |
142 | 173 | struct hostapd_channel_data *first_chan, *chan; |
143 | 174 | int i; |
176 | 207 | return 0; |
177 | 208 | } |
178 | 209 | |
179 | if (!dfs_channel_available(chan, skip_radar)) { | |
210 | if (!dfs_channel_available(chan, type)) { | |
180 | 211 | wpa_printf(MSG_DEBUG, "DFS: channel not available %d", |
181 | 212 | first_chan->freq + i * 20); |
182 | 213 | return 0; |
206 | 237 | */ |
207 | 238 | static int dfs_find_channel(struct hostapd_iface *iface, |
208 | 239 | struct hostapd_channel_data **ret_chan, |
209 | int idx, int skip_radar) | |
240 | int idx, enum dfs_channel_type type) | |
210 | 241 | { |
211 | 242 | struct hostapd_hw_modes *mode; |
212 | 243 | struct hostapd_channel_data *chan; |
231 | 262 | } |
232 | 263 | |
233 | 264 | /* Skip incompatible chandefs */ |
234 | if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) { | |
265 | if (!dfs_chan_range_available(mode, i, n_chans, type)) { | |
235 | 266 | wpa_printf(MSG_DEBUG, |
236 | 267 | "DFS: range not available for %d (%d)", |
237 | 268 | chan->freq, chan->chan); |
474 | 505 | int *secondary_channel, |
475 | 506 | u8 *oper_centr_freq_seg0_idx, |
476 | 507 | u8 *oper_centr_freq_seg1_idx, |
477 | int skip_radar) | |
508 | enum dfs_channel_type type) | |
478 | 509 | { |
479 | 510 | struct hostapd_hw_modes *mode; |
480 | 511 | struct hostapd_channel_data *chan = NULL; |
498 | 529 | return NULL; |
499 | 530 | |
500 | 531 | /* Get the count first */ |
501 | num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar); | |
532 | num_available_chandefs = dfs_find_channel(iface, NULL, 0, type); | |
502 | 533 | wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d", |
503 | 534 | num_available_chandefs); |
504 | 535 | if (num_available_chandefs == 0) |
507 | 538 | if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) |
508 | 539 | return NULL; |
509 | 540 | chan_idx = _rand % num_available_chandefs; |
510 | dfs_find_channel(iface, &chan, chan_idx, skip_radar); | |
541 | dfs_find_channel(iface, &chan, chan_idx, type); | |
511 | 542 | if (!chan) { |
512 | 543 | wpa_printf(MSG_DEBUG, "DFS: no random channel found"); |
513 | 544 | return NULL; |
536 | 567 | for (i = 0; i < num_available_chandefs - 1; i++) { |
537 | 568 | /* start from chan_idx + 1, end when chan_idx - 1 */ |
538 | 569 | chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs; |
539 | dfs_find_channel(iface, &chan2, chan_idx2, skip_radar); | |
570 | dfs_find_channel(iface, &chan2, chan_idx2, type); | |
540 | 571 | if (chan2 && abs(chan2->chan - chan->chan) > 12) { |
541 | 572 | /* two channels are not adjacent */ |
542 | 573 | sec_chan_idx_80p80 = chan2->chan; |
564 | 595 | oper_centr_freq_seg1_idx); |
565 | 596 | |
566 | 597 | return chan; |
598 | } | |
599 | ||
600 | ||
601 | static int dfs_set_valid_channel(struct hostapd_iface *iface, int skip_radar) | |
602 | { | |
603 | struct hostapd_channel_data *channel; | |
604 | u8 cf1 = 0, cf2 = 0; | |
605 | int sec = 0; | |
606 | ||
607 | channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, | |
608 | skip_radar ? DFS_AVAILABLE : | |
609 | DFS_ANY_CHANNEL); | |
610 | if (!channel) { | |
611 | wpa_printf(MSG_ERROR, "could not get valid channel"); | |
612 | return -1; | |
613 | } | |
614 | ||
615 | iface->freq = channel->freq; | |
616 | iface->conf->channel = channel->chan; | |
617 | iface->conf->secondary_channel = sec; | |
618 | hostapd_set_oper_centr_freq_seg0_idx(iface->conf, cf1); | |
619 | hostapd_set_oper_centr_freq_seg1_idx(iface->conf, cf2); | |
620 | ||
621 | return 0; | |
567 | 622 | } |
568 | 623 | |
569 | 624 | |
754 | 809 | */ |
755 | 810 | int hostapd_handle_dfs(struct hostapd_iface *iface) |
756 | 811 | { |
757 | struct hostapd_channel_data *channel; | |
758 | 812 | int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1; |
759 | 813 | int skip_radar = 0; |
760 | 814 | |
809 | 863 | wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s", |
810 | 864 | res, res ? "yes": "no"); |
811 | 865 | if (res) { |
812 | int sec = 0; | |
813 | u8 cf1 = 0, cf2 = 0; | |
814 | ||
815 | channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, | |
816 | skip_radar); | |
817 | if (!channel) { | |
818 | wpa_printf(MSG_ERROR, "could not get valid channel"); | |
866 | if (dfs_set_valid_channel(iface, skip_radar) < 0) { | |
819 | 867 | hostapd_set_state(iface, HAPD_IFACE_DFS); |
820 | 868 | return 0; |
821 | 869 | } |
822 | ||
823 | iface->freq = channel->freq; | |
824 | iface->conf->channel = channel->chan; | |
825 | iface->conf->secondary_channel = sec; | |
826 | hostapd_set_oper_centr_freq_seg0_idx(iface->conf, cf1); | |
827 | hostapd_set_oper_centr_freq_seg1_idx(iface->conf, cf2); | |
828 | 870 | } |
829 | 871 | } while (res); |
830 | 872 | |
831 | 873 | /* Finally start CAC */ |
832 | 874 | hostapd_set_state(iface, HAPD_IFACE_DFS); |
833 | wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq); | |
875 | wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz%s", iface->freq, | |
876 | dfs_use_radar_background(iface) ? " (background)" : ""); | |
834 | 877 | wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START |
835 | 878 | "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds", |
836 | 879 | iface->freq, |
847 | 890 | iface->conf->secondary_channel, |
848 | 891 | hostapd_get_oper_chwidth(iface->conf), |
849 | 892 | hostapd_get_oper_centr_freq_seg0_idx(iface->conf), |
850 | hostapd_get_oper_centr_freq_seg1_idx(iface->conf)); | |
893 | hostapd_get_oper_centr_freq_seg1_idx(iface->conf), | |
894 | dfs_use_radar_background(iface)); | |
851 | 895 | |
852 | 896 | if (res) { |
853 | 897 | wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res); |
854 | 898 | return -1; |
855 | 899 | } |
856 | 900 | |
901 | if (dfs_use_radar_background(iface)) { | |
902 | /* Cache background radar parameters. */ | |
903 | iface->radar_background.channel = iface->conf->channel; | |
904 | iface->radar_background.secondary_channel = | |
905 | iface->conf->secondary_channel; | |
906 | iface->radar_background.freq = iface->freq; | |
907 | iface->radar_background.centr_freq_seg0_idx = | |
908 | hostapd_get_oper_centr_freq_seg0_idx(iface->conf); | |
909 | iface->radar_background.centr_freq_seg1_idx = | |
910 | hostapd_get_oper_centr_freq_seg1_idx(iface->conf); | |
911 | ||
912 | /* | |
913 | * Let's select a random channel according to the | |
914 | * regulations and perform CAC on dedicated radar chain. | |
915 | */ | |
916 | res = dfs_set_valid_channel(iface, 1); | |
917 | if (res < 0) | |
918 | return res; | |
919 | ||
920 | iface->radar_background.temp_ch = 1; | |
921 | return 1; | |
922 | } | |
923 | ||
857 | 924 | return 0; |
858 | 925 | } |
859 | 926 | |
872 | 939 | |
873 | 940 | /* Check if all channels are DFS available */ |
874 | 941 | return dfs_check_chans_available(iface, start_chan_idx, n_chans); |
942 | } | |
943 | ||
944 | ||
945 | static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface, | |
946 | int channel, int freq, | |
947 | int secondary_channel, | |
948 | u8 current_vht_oper_chwidth, | |
949 | u8 oper_centr_freq_seg0_idx, | |
950 | u8 oper_centr_freq_seg1_idx) | |
951 | { | |
952 | struct hostapd_hw_modes *cmode = iface->current_mode; | |
953 | int ieee80211_mode = IEEE80211_MODE_AP, err; | |
954 | struct csa_settings csa_settings; | |
955 | u8 new_vht_oper_chwidth; | |
956 | unsigned int i; | |
957 | ||
958 | wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel); | |
959 | wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL | |
960 | "freq=%d chan=%d sec_chan=%d", freq, channel, | |
961 | secondary_channel); | |
962 | ||
963 | new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); | |
964 | hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth); | |
965 | ||
966 | /* Setup CSA request */ | |
967 | os_memset(&csa_settings, 0, sizeof(csa_settings)); | |
968 | csa_settings.cs_count = 5; | |
969 | csa_settings.block_tx = 1; | |
970 | #ifdef CONFIG_MESH | |
971 | if (iface->mconf) | |
972 | ieee80211_mode = IEEE80211_MODE_MESH; | |
973 | #endif /* CONFIG_MESH */ | |
974 | err = hostapd_set_freq_params(&csa_settings.freq_params, | |
975 | iface->conf->hw_mode, | |
976 | freq, channel, | |
977 | iface->conf->enable_edmg, | |
978 | iface->conf->edmg_channel, | |
979 | iface->conf->ieee80211n, | |
980 | iface->conf->ieee80211ac, | |
981 | iface->conf->ieee80211ax, | |
982 | secondary_channel, | |
983 | new_vht_oper_chwidth, | |
984 | oper_centr_freq_seg0_idx, | |
985 | oper_centr_freq_seg1_idx, | |
986 | cmode->vht_capab, | |
987 | &cmode->he_capab[ieee80211_mode]); | |
988 | ||
989 | if (err) { | |
990 | wpa_printf(MSG_ERROR, | |
991 | "DFS failed to calculate CSA freq params"); | |
992 | hostapd_disable_iface(iface); | |
993 | return err; | |
994 | } | |
995 | ||
996 | for (i = 0; i < iface->num_bss; i++) { | |
997 | err = hostapd_switch_channel(iface->bss[i], &csa_settings); | |
998 | if (err) | |
999 | break; | |
1000 | } | |
1001 | ||
1002 | if (err) { | |
1003 | wpa_printf(MSG_WARNING, | |
1004 | "DFS failed to schedule CSA (%d) - trying fallback", | |
1005 | err); | |
1006 | iface->freq = freq; | |
1007 | iface->conf->channel = channel; | |
1008 | iface->conf->secondary_channel = secondary_channel; | |
1009 | hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth); | |
1010 | hostapd_set_oper_centr_freq_seg0_idx(iface->conf, | |
1011 | oper_centr_freq_seg0_idx); | |
1012 | hostapd_set_oper_centr_freq_seg1_idx(iface->conf, | |
1013 | oper_centr_freq_seg1_idx); | |
1014 | ||
1015 | hostapd_disable_iface(iface); | |
1016 | hostapd_enable_iface(iface); | |
1017 | ||
1018 | return 0; | |
1019 | } | |
1020 | ||
1021 | /* Channel configuration will be updated once CSA completes and | |
1022 | * ch_switch_notify event is received */ | |
1023 | wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); | |
1024 | ||
1025 | return 0; | |
1026 | } | |
1027 | ||
1028 | ||
1029 | static void hostpad_dfs_update_background_chain(struct hostapd_iface *iface) | |
1030 | { | |
1031 | int sec = 0; | |
1032 | enum dfs_channel_type channel_type = DFS_NO_CAC_YET; | |
1033 | struct hostapd_channel_data *channel; | |
1034 | u8 oper_centr_freq_seg0_idx = 0; | |
1035 | u8 oper_centr_freq_seg1_idx = 0; | |
1036 | ||
1037 | /* | |
1038 | * Allow selection of DFS channel in ETSI to comply with | |
1039 | * uniform spreading. | |
1040 | */ | |
1041 | if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI) | |
1042 | channel_type = DFS_ANY_CHANNEL; | |
1043 | ||
1044 | channel = dfs_get_valid_channel(iface, &sec, &oper_centr_freq_seg0_idx, | |
1045 | &oper_centr_freq_seg1_idx, | |
1046 | channel_type); | |
1047 | if (!channel || | |
1048 | channel->chan == iface->conf->channel || | |
1049 | channel->chan == iface->radar_background.channel) | |
1050 | channel = dfs_downgrade_bandwidth(iface, &sec, | |
1051 | &oper_centr_freq_seg0_idx, | |
1052 | &oper_centr_freq_seg1_idx, | |
1053 | &channel_type); | |
1054 | if (!channel || | |
1055 | hostapd_start_dfs_cac(iface, iface->conf->hw_mode, | |
1056 | channel->freq, channel->chan, | |
1057 | iface->conf->ieee80211n, | |
1058 | iface->conf->ieee80211ac, | |
1059 | iface->conf->ieee80211ax, | |
1060 | sec, hostapd_get_oper_chwidth(iface->conf), | |
1061 | oper_centr_freq_seg0_idx, | |
1062 | oper_centr_freq_seg1_idx, true)) { | |
1063 | wpa_printf(MSG_ERROR, "DFS failed to start CAC offchannel"); | |
1064 | iface->radar_background.channel = -1; | |
1065 | return; | |
1066 | } | |
1067 | ||
1068 | iface->radar_background.channel = channel->chan; | |
1069 | iface->radar_background.freq = channel->freq; | |
1070 | iface->radar_background.secondary_channel = sec; | |
1071 | iface->radar_background.centr_freq_seg0_idx = oper_centr_freq_seg0_idx; | |
1072 | iface->radar_background.centr_freq_seg1_idx = oper_centr_freq_seg1_idx; | |
1073 | ||
1074 | wpa_printf(MSG_DEBUG, | |
1075 | "%s: setting background chain to chan %d (%d MHz)", | |
1076 | __func__, channel->chan, channel->freq); | |
1077 | } | |
1078 | ||
1079 | ||
1080 | static bool | |
1081 | hostapd_dfs_is_background_event(struct hostapd_iface *iface, int freq) | |
1082 | { | |
1083 | return dfs_use_radar_background(iface) && | |
1084 | iface->radar_background.channel != -1 && | |
1085 | iface->radar_background.freq == freq; | |
1086 | } | |
1087 | ||
1088 | ||
1089 | static int | |
1090 | hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface) | |
1091 | { | |
1092 | u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); | |
1093 | ||
1094 | iface->conf->channel = iface->radar_background.channel; | |
1095 | iface->freq = iface->radar_background.freq; | |
1096 | iface->conf->secondary_channel = | |
1097 | iface->radar_background.secondary_channel; | |
1098 | hostapd_set_oper_centr_freq_seg0_idx( | |
1099 | iface->conf, iface->radar_background.centr_freq_seg0_idx); | |
1100 | hostapd_set_oper_centr_freq_seg1_idx( | |
1101 | iface->conf, iface->radar_background.centr_freq_seg1_idx); | |
1102 | ||
1103 | hostpad_dfs_update_background_chain(iface); | |
1104 | ||
1105 | return hostapd_dfs_request_channel_switch( | |
1106 | iface, iface->conf->channel, iface->freq, | |
1107 | iface->conf->secondary_channel, current_vht_oper_chwidth, | |
1108 | hostapd_get_oper_centr_freq_seg0_idx(iface->conf), | |
1109 | hostapd_get_oper_centr_freq_seg1_idx(iface->conf)); | |
875 | 1110 | } |
876 | 1111 | |
877 | 1112 | |
895 | 1130 | set_dfs_state(iface, freq, ht_enabled, chan_offset, |
896 | 1131 | chan_width, cf1, cf2, |
897 | 1132 | HOSTAPD_CHAN_DFS_AVAILABLE); |
1133 | ||
1134 | /* | |
1135 | * Radar event from background chain for the selected | |
1136 | * channel. Perform CSA, move the main chain to the | |
1137 | * selected channel and configure the background chain | |
1138 | * to a new DFS channel. | |
1139 | */ | |
1140 | if (hostapd_dfs_is_background_event(iface, freq)) { | |
1141 | iface->radar_background.cac_started = 0; | |
1142 | if (!iface->radar_background.temp_ch) | |
1143 | return 0; | |
1144 | ||
1145 | iface->radar_background.temp_ch = 0; | |
1146 | return hostapd_dfs_start_channel_switch_background(iface); | |
1147 | } | |
1148 | ||
898 | 1149 | /* |
899 | 1150 | * Just mark the channel available when CAC completion |
900 | 1151 | * event is received in enabled state. CAC result could |
911 | 1162 | iface->cac_started = 0; |
912 | 1163 | } |
913 | 1164 | } |
1165 | } else if (hostapd_dfs_is_background_event(iface, freq)) { | |
1166 | iface->radar_background.cac_started = 0; | |
1167 | hostpad_dfs_update_background_chain(iface); | |
914 | 1168 | } |
915 | 1169 | |
916 | 1170 | return 0; |
939 | 1193 | static struct hostapd_channel_data * |
940 | 1194 | dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, |
941 | 1195 | u8 *oper_centr_freq_seg0_idx, |
942 | u8 *oper_centr_freq_seg1_idx, int *skip_radar) | |
1196 | u8 *oper_centr_freq_seg1_idx, | |
1197 | enum dfs_channel_type *channel_type) | |
943 | 1198 | { |
944 | 1199 | struct hostapd_channel_data *channel; |
945 | 1200 | |
947 | 1202 | channel = dfs_get_valid_channel(iface, secondary_channel, |
948 | 1203 | oper_centr_freq_seg0_idx, |
949 | 1204 | oper_centr_freq_seg1_idx, |
950 | *skip_radar); | |
1205 | *channel_type); | |
951 | 1206 | if (channel) { |
952 | 1207 | wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d", |
953 | 1208 | channel->chan); |
954 | 1209 | return channel; |
955 | 1210 | } |
956 | 1211 | |
957 | if (*skip_radar) { | |
958 | *skip_radar = 0; | |
1212 | if (*channel_type != DFS_ANY_CHANNEL) { | |
1213 | *channel_type = DFS_ANY_CHANNEL; | |
959 | 1214 | } else { |
960 | 1215 | int oper_chwidth; |
961 | 1216 | |
962 | 1217 | oper_chwidth = hostapd_get_oper_chwidth(iface->conf); |
963 | 1218 | if (oper_chwidth == CHANWIDTH_USE_HT) |
964 | 1219 | break; |
965 | *skip_radar = 1; | |
1220 | *channel_type = DFS_AVAILABLE; | |
966 | 1221 | hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1); |
967 | 1222 | } |
968 | 1223 | } |
980 | 1235 | int secondary_channel; |
981 | 1236 | u8 oper_centr_freq_seg0_idx = 0; |
982 | 1237 | u8 oper_centr_freq_seg1_idx = 0; |
983 | int skip_radar = 0; | |
1238 | enum dfs_channel_type channel_type = DFS_ANY_CHANNEL; | |
984 | 1239 | int err = 1; |
985 | 1240 | |
986 | 1241 | /* Radar detected during active CAC */ |
988 | 1243 | channel = dfs_get_valid_channel(iface, &secondary_channel, |
989 | 1244 | &oper_centr_freq_seg0_idx, |
990 | 1245 | &oper_centr_freq_seg1_idx, |
991 | skip_radar); | |
1246 | channel_type); | |
992 | 1247 | |
993 | 1248 | if (!channel) { |
994 | 1249 | channel = dfs_downgrade_bandwidth(iface, &secondary_channel, |
995 | 1250 | &oper_centr_freq_seg0_idx, |
996 | 1251 | &oper_centr_freq_seg1_idx, |
997 | &skip_radar); | |
1252 | &channel_type); | |
998 | 1253 | if (!channel) { |
999 | 1254 | wpa_printf(MSG_ERROR, "No valid channel available"); |
1000 | 1255 | return err; |
1021 | 1276 | } |
1022 | 1277 | |
1023 | 1278 | |
1279 | static int | |
1280 | hostapd_dfs_background_start_channel_switch(struct hostapd_iface *iface, | |
1281 | int freq) | |
1282 | { | |
1283 | if (!dfs_use_radar_background(iface)) | |
1284 | return -1; /* Background radar chain not supported. */ | |
1285 | ||
1286 | wpa_printf(MSG_DEBUG, | |
1287 | "%s called (background CAC active: %s, CSA active: %s)", | |
1288 | __func__, iface->radar_background.cac_started ? "yes" : "no", | |
1289 | hostapd_csa_in_progress(iface) ? "yes" : "no"); | |
1290 | ||
1291 | /* Check if CSA in progress */ | |
1292 | if (hostapd_csa_in_progress(iface)) | |
1293 | return 0; | |
1294 | ||
1295 | if (hostapd_dfs_is_background_event(iface, freq)) { | |
1296 | /* | |
1297 | * Radar pattern is reported on the background chain. | |
1298 | * Just select a new random channel according to the | |
1299 | * regulations for monitoring. | |
1300 | */ | |
1301 | hostpad_dfs_update_background_chain(iface); | |
1302 | return 0; | |
1303 | } | |
1304 | ||
1305 | /* | |
1306 | * If background radar detection is supported and the radar channel | |
1307 | * monitored by the background chain is available switch to it without | |
1308 | * waiting for the CAC. | |
1309 | */ | |
1310 | if (iface->radar_background.channel == -1) | |
1311 | return -1; /* Background radar chain not available. */ | |
1312 | ||
1313 | if (iface->radar_background.cac_started) { | |
1314 | /* | |
1315 | * Background channel not available yet. Perform CAC on the | |
1316 | * main chain. | |
1317 | */ | |
1318 | iface->radar_background.temp_ch = 1; | |
1319 | return -1; | |
1320 | } | |
1321 | ||
1322 | return hostapd_dfs_start_channel_switch_background(iface); | |
1323 | } | |
1324 | ||
1325 | ||
1024 | 1326 | static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) |
1025 | 1327 | { |
1026 | 1328 | struct hostapd_channel_data *channel; |
1027 | 1329 | int secondary_channel; |
1028 | 1330 | u8 oper_centr_freq_seg0_idx; |
1029 | 1331 | u8 oper_centr_freq_seg1_idx; |
1030 | u8 new_vht_oper_chwidth; | |
1031 | int skip_radar = 1; | |
1032 | struct csa_settings csa_settings; | |
1033 | unsigned int i; | |
1034 | int err = 1; | |
1035 | struct hostapd_hw_modes *cmode = iface->current_mode; | |
1332 | enum dfs_channel_type channel_type = DFS_AVAILABLE; | |
1036 | 1333 | u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); |
1037 | int ieee80211_mode = IEEE80211_MODE_AP; | |
1038 | 1334 | |
1039 | 1335 | wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", |
1040 | 1336 | __func__, iface->cac_started ? "yes" : "no", |
1053 | 1349 | * uniform spreading. |
1054 | 1350 | */ |
1055 | 1351 | if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI) |
1056 | skip_radar = 0; | |
1352 | channel_type = DFS_ANY_CHANNEL; | |
1057 | 1353 | |
1058 | 1354 | /* Perform channel switch/CSA */ |
1059 | 1355 | channel = dfs_get_valid_channel(iface, &secondary_channel, |
1060 | 1356 | &oper_centr_freq_seg0_idx, |
1061 | 1357 | &oper_centr_freq_seg1_idx, |
1062 | skip_radar); | |
1358 | channel_type); | |
1063 | 1359 | |
1064 | 1360 | if (!channel) { |
1065 | 1361 | /* |
1067 | 1363 | * there is another channel where we can switch even if it |
1068 | 1364 | * requires to perform a CAC first. |
1069 | 1365 | */ |
1070 | skip_radar = 0; | |
1366 | channel_type = DFS_ANY_CHANNEL; | |
1071 | 1367 | channel = dfs_downgrade_bandwidth(iface, &secondary_channel, |
1072 | 1368 | &oper_centr_freq_seg0_idx, |
1073 | 1369 | &oper_centr_freq_seg1_idx, |
1074 | &skip_radar); | |
1370 | &channel_type); | |
1075 | 1371 | if (!channel) { |
1076 | 1372 | /* |
1077 | 1373 | * Toggle interface state to enter DFS state |
1082 | 1378 | return 0; |
1083 | 1379 | } |
1084 | 1380 | |
1085 | if (!skip_radar) { | |
1381 | if (channel_type == DFS_ANY_CHANNEL) { | |
1086 | 1382 | iface->freq = channel->freq; |
1087 | 1383 | iface->conf->channel = channel->chan; |
1088 | 1384 | iface->conf->secondary_channel = secondary_channel; |
1097 | 1393 | } |
1098 | 1394 | } |
1099 | 1395 | |
1100 | wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", | |
1101 | channel->chan); | |
1102 | wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL | |
1103 | "freq=%d chan=%d sec_chan=%d", channel->freq, | |
1104 | channel->chan, secondary_channel); | |
1105 | ||
1106 | new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); | |
1107 | hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth); | |
1108 | ||
1109 | /* Setup CSA request */ | |
1110 | os_memset(&csa_settings, 0, sizeof(csa_settings)); | |
1111 | csa_settings.cs_count = 5; | |
1112 | csa_settings.block_tx = 1; | |
1113 | #ifdef CONFIG_MESH | |
1114 | if (iface->mconf) | |
1115 | ieee80211_mode = IEEE80211_MODE_MESH; | |
1116 | #endif /* CONFIG_MESH */ | |
1117 | err = hostapd_set_freq_params(&csa_settings.freq_params, | |
1118 | iface->conf->hw_mode, | |
1119 | channel->freq, | |
1120 | channel->chan, | |
1121 | iface->conf->enable_edmg, | |
1122 | iface->conf->edmg_channel, | |
1123 | iface->conf->ieee80211n, | |
1124 | iface->conf->ieee80211ac, | |
1125 | iface->conf->ieee80211ax, | |
1126 | secondary_channel, | |
1127 | new_vht_oper_chwidth, | |
1128 | oper_centr_freq_seg0_idx, | |
1129 | oper_centr_freq_seg1_idx, | |
1130 | cmode->vht_capab, | |
1131 | &cmode->he_capab[ieee80211_mode]); | |
1132 | ||
1133 | if (err) { | |
1134 | wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); | |
1135 | hostapd_disable_iface(iface); | |
1136 | return err; | |
1137 | } | |
1138 | ||
1139 | for (i = 0; i < iface->num_bss; i++) { | |
1140 | err = hostapd_switch_channel(iface->bss[i], &csa_settings); | |
1141 | if (err) | |
1142 | break; | |
1143 | } | |
1144 | ||
1145 | if (err) { | |
1146 | wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback", | |
1147 | err); | |
1148 | iface->freq = channel->freq; | |
1149 | iface->conf->channel = channel->chan; | |
1150 | iface->conf->secondary_channel = secondary_channel; | |
1151 | hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth); | |
1152 | hostapd_set_oper_centr_freq_seg0_idx(iface->conf, | |
1153 | oper_centr_freq_seg0_idx); | |
1154 | hostapd_set_oper_centr_freq_seg1_idx(iface->conf, | |
1155 | oper_centr_freq_seg1_idx); | |
1156 | ||
1157 | hostapd_disable_iface(iface); | |
1158 | hostapd_enable_iface(iface); | |
1159 | return 0; | |
1160 | } | |
1161 | ||
1162 | /* Channel configuration will be updated once CSA completes and | |
1163 | * ch_switch_notify event is received */ | |
1164 | ||
1165 | wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); | |
1166 | return 0; | |
1396 | return hostapd_dfs_request_channel_switch(iface, channel->chan, | |
1397 | channel->freq, | |
1398 | secondary_channel, | |
1399 | current_vht_oper_chwidth, | |
1400 | oper_centr_freq_seg0_idx, | |
1401 | oper_centr_freq_seg1_idx); | |
1167 | 1402 | } |
1168 | 1403 | |
1169 | 1404 | |
1171 | 1406 | int ht_enabled, int chan_offset, int chan_width, |
1172 | 1407 | int cf1, int cf2) |
1173 | 1408 | { |
1174 | int res; | |
1175 | ||
1176 | 1409 | wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED |
1177 | 1410 | "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", |
1178 | 1411 | freq, ht_enabled, chan_offset, chan_width, cf1, cf2); |
1185 | 1418 | return 0; |
1186 | 1419 | |
1187 | 1420 | /* mark radar frequency as invalid */ |
1188 | res = set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, | |
1189 | cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); | |
1190 | if (!res) | |
1191 | return 0; | |
1192 | ||
1193 | /* Skip if reported radar event not overlapped our channels */ | |
1194 | res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); | |
1195 | if (!res) | |
1196 | return 0; | |
1197 | ||
1198 | /* radar detected while operating, switch the channel. */ | |
1199 | res = hostapd_dfs_start_channel_switch(iface); | |
1200 | ||
1201 | return res; | |
1421 | if (!set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, | |
1422 | cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE)) | |
1423 | return 0; | |
1424 | ||
1425 | if (!hostapd_dfs_is_background_event(iface, freq)) { | |
1426 | /* Skip if reported radar event not overlapped our channels */ | |
1427 | if (!dfs_are_channels_overlapped(iface, freq, chan_width, | |
1428 | cf1, cf2)) | |
1429 | return 0; | |
1430 | } | |
1431 | ||
1432 | if (hostapd_dfs_background_start_channel_switch(iface, freq)) { | |
1433 | /* Radar detected while operating, switch the channel. */ | |
1434 | return hostapd_dfs_start_channel_switch(iface); | |
1435 | } | |
1436 | ||
1437 | return 0; | |
1202 | 1438 | } |
1203 | 1439 | |
1204 | 1440 | |
1218 | 1454 | set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, |
1219 | 1455 | cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); |
1220 | 1456 | |
1221 | /* Handle cases where all channels were initially unavailable */ | |
1222 | if (iface->state == HAPD_IFACE_DFS && !iface->cac_started) | |
1457 | if (iface->state == HAPD_IFACE_DFS && !iface->cac_started) { | |
1458 | /* Handle cases where all channels were initially unavailable */ | |
1223 | 1459 | hostapd_handle_dfs(iface); |
1460 | } else if (dfs_use_radar_background(iface) && | |
1461 | iface->radar_background.channel == -1) { | |
1462 | /* Reset radar background chain if disabled */ | |
1463 | hostpad_dfs_update_background_chain(iface); | |
1464 | } | |
1224 | 1465 | |
1225 | 1466 | return 0; |
1226 | 1467 | } |
1258 | 1499 | int ht_enabled, int chan_offset, int chan_width, |
1259 | 1500 | int cf1, int cf2) |
1260 | 1501 | { |
1261 | /* This is called when the driver indicates that an offloaded DFS has | |
1262 | * started CAC. */ | |
1263 | hostapd_set_state(iface, HAPD_IFACE_DFS); | |
1502 | if (hostapd_dfs_is_background_event(iface, freq)) { | |
1503 | iface->radar_background.cac_started = 1; | |
1504 | } else { | |
1505 | /* This is called when the driver indicates that an offloaded | |
1506 | * DFS has started CAC. */ | |
1507 | hostapd_set_state(iface, HAPD_IFACE_DFS); | |
1508 | iface->cac_started = 1; | |
1509 | } | |
1264 | 1510 | /* TODO: How to check CAC time for ETSI weather channels? */ |
1265 | 1511 | iface->dfs_cac_ms = 60000; |
1266 | 1512 | wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START |
1267 | 1513 | "freq=%d chan=%d chan_offset=%d width=%d seg0=%d " |
1268 | "seg1=%d cac_time=%ds", | |
1514 | "seg1=%d cac_time=%ds%s", | |
1269 | 1515 | freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, |
1270 | iface->dfs_cac_ms / 1000); | |
1271 | iface->cac_started = 1; | |
1516 | iface->dfs_cac_ms / 1000, | |
1517 | hostapd_dfs_is_background_event(iface, freq) ? | |
1518 | " (background)" : ""); | |
1519 | ||
1272 | 1520 | os_get_reltime(&iface->dfs_cac_start); |
1273 | 1521 | return 0; |
1274 | 1522 | } |
1 | 1 | * hostapd / DPP integration |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2018-2020, The Linux Foundation |
4 | * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
27 | 28 | static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator); |
28 | 29 | static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx); |
29 | 30 | static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd); |
31 | static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd, | |
32 | struct dpp_authentication *auth); | |
33 | static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd); | |
30 | 34 | #ifdef CONFIG_DPP2 |
31 | 35 | static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, |
32 | 36 | void *timeout_ctx); |
33 | 37 | static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd, |
34 | 38 | struct dpp_authentication *auth, |
35 | 39 | struct dpp_config_obj *conf); |
40 | static int hostapd_dpp_process_conf_obj(void *ctx, | |
41 | struct dpp_authentication *auth); | |
36 | 42 | #endif /* CONFIG_DPP2 */ |
37 | 43 | |
38 | 44 | static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
215 | 221 | } |
216 | 222 | |
217 | 223 | |
224 | static int hostapd_dpp_allow_ir(struct hostapd_data *hapd, unsigned int freq) | |
225 | { | |
226 | int i, j; | |
227 | ||
228 | if (!hapd->iface->hw_features) | |
229 | return -1; | |
230 | ||
231 | for (i = 0; i < hapd->iface->num_hw_features; i++) { | |
232 | struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i]; | |
233 | ||
234 | for (j = 0; j < mode->num_channels; j++) { | |
235 | struct hostapd_channel_data *chan = &mode->channels[j]; | |
236 | ||
237 | if (chan->freq != (int) freq) | |
238 | continue; | |
239 | ||
240 | if (chan->flag & (HOSTAPD_CHAN_DISABLED | | |
241 | HOSTAPD_CHAN_NO_IR | | |
242 | HOSTAPD_CHAN_RADAR)) | |
243 | continue; | |
244 | ||
245 | return 1; | |
246 | } | |
247 | } | |
248 | ||
249 | wpa_printf(MSG_DEBUG, | |
250 | "DPP: Frequency %u MHz not supported or does not allow PKEX initiation in the current channel list", | |
251 | freq); | |
252 | ||
253 | return 0; | |
254 | } | |
255 | ||
256 | ||
257 | static int hostapd_dpp_pkex_next_channel(struct hostapd_data *hapd, | |
258 | struct dpp_pkex *pkex) | |
259 | { | |
260 | if (pkex->freq == 2437) | |
261 | pkex->freq = 5745; | |
262 | else if (pkex->freq == 5745) | |
263 | pkex->freq = 5220; | |
264 | else if (pkex->freq == 5220) | |
265 | pkex->freq = 60480; | |
266 | else | |
267 | return -1; /* no more channels to try */ | |
268 | ||
269 | if (hostapd_dpp_allow_ir(hapd, pkex->freq) == 1) { | |
270 | wpa_printf(MSG_DEBUG, "DPP: Try to initiate on %u MHz", | |
271 | pkex->freq); | |
272 | return 0; | |
273 | } | |
274 | ||
275 | /* Could not use this channel - try the next one */ | |
276 | return hostapd_dpp_pkex_next_channel(hapd, pkex); | |
277 | } | |
278 | ||
279 | ||
280 | #ifdef CONFIG_DPP2 | |
281 | static int hostapd_dpp_pkex_done(void *ctx, void *conn, | |
282 | struct dpp_bootstrap_info *peer_bi) | |
283 | { | |
284 | struct hostapd_data *hapd = ctx; | |
285 | const char *cmd = hapd->dpp_pkex_auth_cmd; | |
286 | const char *pos; | |
287 | u8 allowed_roles = DPP_CAPAB_CONFIGURATOR; | |
288 | struct dpp_bootstrap_info *own_bi = NULL; | |
289 | struct dpp_authentication *auth; | |
290 | ||
291 | if (!cmd) | |
292 | cmd = ""; | |
293 | wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)", | |
294 | cmd); | |
295 | ||
296 | pos = os_strstr(cmd, " own="); | |
297 | if (pos) { | |
298 | pos += 5; | |
299 | own_bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, | |
300 | atoi(pos)); | |
301 | if (!own_bi) { | |
302 | wpa_printf(MSG_INFO, | |
303 | "DPP: Could not find bootstrapping info for the identified local entry"); | |
304 | return -1; | |
305 | } | |
306 | ||
307 | if (peer_bi->curve != own_bi->curve) { | |
308 | wpa_printf(MSG_INFO, | |
309 | "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)", | |
310 | peer_bi->curve->name, own_bi->curve->name); | |
311 | return -1; | |
312 | } | |
313 | } | |
314 | ||
315 | pos = os_strstr(cmd, " role="); | |
316 | if (pos) { | |
317 | pos += 6; | |
318 | if (os_strncmp(pos, "configurator", 12) == 0) | |
319 | allowed_roles = DPP_CAPAB_CONFIGURATOR; | |
320 | else if (os_strncmp(pos, "enrollee", 8) == 0) | |
321 | allowed_roles = DPP_CAPAB_ENROLLEE; | |
322 | else if (os_strncmp(pos, "either", 6) == 0) | |
323 | allowed_roles = DPP_CAPAB_CONFIGURATOR | | |
324 | DPP_CAPAB_ENROLLEE; | |
325 | else | |
326 | return -1; | |
327 | } | |
328 | ||
329 | auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, | |
330 | peer_bi, own_bi, allowed_roles, 0, | |
331 | hapd->iface->hw_features, | |
332 | hapd->iface->num_hw_features); | |
333 | if (!auth) | |
334 | return -1; | |
335 | ||
336 | hostapd_dpp_set_testing_options(hapd, auth); | |
337 | if (dpp_set_configurator(auth, cmd) < 0) { | |
338 | dpp_auth_deinit(auth); | |
339 | return -1; | |
340 | } | |
341 | ||
342 | return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth, | |
343 | hapd->conf->dpp_name, DPP_NETROLE_AP, | |
344 | hostapd_dpp_process_conf_obj, NULL); | |
345 | } | |
346 | #endif /* CONFIG_DPP2 */ | |
347 | ||
348 | ||
349 | static int hostapd_dpp_pkex_init(struct hostapd_data *hapd, | |
350 | enum dpp_pkex_ver ver, | |
351 | const struct hostapd_ip_addr *ipaddr, | |
352 | int tcp_port) | |
353 | { | |
354 | struct dpp_pkex *pkex; | |
355 | struct wpabuf *msg; | |
356 | unsigned int wait_time; | |
357 | bool v2 = ver != PKEX_VER_ONLY_1; | |
358 | ||
359 | wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1); | |
360 | dpp_pkex_free(hapd->dpp_pkex); | |
361 | hapd->dpp_pkex = NULL; | |
362 | pkex = dpp_pkex_init(hapd->msg_ctx, hapd->dpp_pkex_bi, hapd->own_addr, | |
363 | hapd->dpp_pkex_identifier, | |
364 | hapd->dpp_pkex_code, v2); | |
365 | if (!pkex) | |
366 | return -1; | |
367 | pkex->forced_ver = ver != PKEX_VER_AUTO; | |
368 | ||
369 | if (ipaddr) { | |
370 | #ifdef CONFIG_DPP2 | |
371 | return dpp_tcp_pkex_init(hapd->iface->interfaces->dpp, pkex, | |
372 | ipaddr, tcp_port, | |
373 | hapd->msg_ctx, hapd, | |
374 | hostapd_dpp_pkex_done); | |
375 | #else /* CONFIG_DPP2 */ | |
376 | return -1; | |
377 | #endif /* CONFIG_DPP2 */ | |
378 | } | |
379 | ||
380 | hapd->dpp_pkex = pkex; | |
381 | msg = hapd->dpp_pkex->exchange_req; | |
382 | wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */ | |
383 | pkex->freq = 2437; | |
384 | wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR | |
385 | " freq=%u type=%d", MAC2STR(broadcast), pkex->freq, | |
386 | v2 ? DPP_PA_PKEX_EXCHANGE_REQ : | |
387 | DPP_PA_PKEX_V1_EXCHANGE_REQ); | |
388 | hostapd_drv_send_action(hapd, pkex->freq, 0, broadcast, | |
389 | wpabuf_head(msg), wpabuf_len(msg)); | |
390 | pkex->exch_req_wait_time = wait_time; | |
391 | pkex->exch_req_tries = 1; | |
392 | ||
393 | return 0; | |
394 | } | |
395 | ||
396 | ||
397 | static void hostapd_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx) | |
398 | { | |
399 | struct hostapd_data *hapd = eloop_ctx; | |
400 | struct dpp_pkex *pkex = hapd->dpp_pkex; | |
401 | ||
402 | if (!pkex || !pkex->exchange_req) | |
403 | return; | |
404 | if (pkex->exch_req_tries >= 5) { | |
405 | if (hostapd_dpp_pkex_next_channel(hapd, pkex) < 0) { | |
406 | #ifdef CONFIG_DPP3 | |
407 | if (pkex->v2 && !pkex->forced_ver) { | |
408 | wpa_printf(MSG_DEBUG, | |
409 | "DPP: Fall back to PKEXv1"); | |
410 | hostapd_dpp_pkex_init(hapd, PKEX_VER_ONLY_1, | |
411 | NULL, 0); | |
412 | return; | |
413 | } | |
414 | #endif /* CONFIG_DPP3 */ | |
415 | wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL | |
416 | "No response from PKEX peer"); | |
417 | dpp_pkex_free(pkex); | |
418 | hapd->dpp_pkex = NULL; | |
419 | return; | |
420 | } | |
421 | pkex->exch_req_tries = 0; | |
422 | } | |
423 | ||
424 | pkex->exch_req_tries++; | |
425 | wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)", | |
426 | pkex->exch_req_tries); | |
427 | wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR | |
428 | " freq=%u type=%d", | |
429 | MAC2STR(broadcast), pkex->freq, | |
430 | pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ : | |
431 | DPP_PA_PKEX_V1_EXCHANGE_REQ); | |
432 | hostapd_drv_send_action(hapd, pkex->freq, pkex->exch_req_wait_time, | |
433 | broadcast, | |
434 | wpabuf_head(pkex->exchange_req), | |
435 | wpabuf_len(pkex->exchange_req)); | |
436 | } | |
437 | ||
438 | ||
439 | static void hostapd_dpp_pkex_tx_status(struct hostapd_data *hapd, const u8 *dst, | |
440 | const u8 *data, size_t data_len, int ok) | |
441 | { | |
442 | struct dpp_pkex *pkex = hapd->dpp_pkex; | |
443 | ||
444 | if (pkex->failed) { | |
445 | wpa_printf(MSG_DEBUG, | |
446 | "DPP: Terminate PKEX exchange due to an earlier error"); | |
447 | if (pkex->t > pkex->own_bi->pkex_t) | |
448 | pkex->own_bi->pkex_t = pkex->t; | |
449 | dpp_pkex_free(pkex); | |
450 | hapd->dpp_pkex = NULL; | |
451 | return; | |
452 | } | |
453 | ||
454 | if (pkex->exch_req_wait_time && pkex->exchange_req) { | |
455 | /* Wait for PKEX Exchange Response frame and retry request if | |
456 | * no response is seen. */ | |
457 | eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, | |
458 | NULL); | |
459 | eloop_register_timeout(pkex->exch_req_wait_time / 1000, | |
460 | (pkex->exch_req_wait_time % 1000) * 1000, | |
461 | hostapd_dpp_pkex_retry_timeout, hapd, | |
462 | NULL); | |
463 | } | |
464 | } | |
465 | ||
466 | ||
218 | 467 | void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst, |
219 | 468 | const u8 *data, size_t data_len, int ok) |
220 | 469 | { |
226 | 475 | " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED"); |
227 | 476 | |
228 | 477 | if (!hapd->dpp_auth) { |
478 | if (hapd->dpp_pkex) { | |
479 | hostapd_dpp_pkex_tx_status(hapd, dst, data, data_len, | |
480 | ok); | |
481 | return; | |
482 | } | |
229 | 483 | wpa_printf(MSG_DEBUG, |
230 | 484 | "DPP: Ignore TX status since there is no ongoing authentication exchange"); |
231 | 485 | return; |
663 | 917 | return dpp_tcp_init(hapd->iface->interfaces->dpp, auth, |
664 | 918 | &ipaddr, tcp_port, hapd->conf->dpp_name, |
665 | 919 | DPP_NETROLE_AP, hapd->msg_ctx, hapd, |
666 | hostapd_dpp_process_conf_obj); | |
920 | hostapd_dpp_process_conf_obj, NULL); | |
667 | 921 | #endif /* CONFIG_DPP2 */ |
668 | 922 | |
669 | 923 | hapd->dpp_auth = auth; |
900 | 1154 | } |
901 | 1155 | |
902 | 1156 | |
1157 | #ifdef CONFIG_DPP3 | |
1158 | static void hostapd_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx) | |
1159 | { | |
1160 | struct hostapd_data *hapd = eloop_ctx; | |
1161 | struct dpp_authentication *auth = hapd->dpp_auth; | |
1162 | ||
1163 | if (!auth || !auth->waiting_new_key) | |
1164 | return; | |
1165 | ||
1166 | wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key"); | |
1167 | hostapd_dpp_start_gas_client(hapd); | |
1168 | } | |
1169 | #endif /* CONFIG_DPP3 */ | |
1170 | ||
1171 | ||
903 | 1172 | static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, |
904 | 1173 | enum gas_query_ap_result result, |
905 | 1174 | const struct wpabuf *adv_proto, |
909 | 1178 | const u8 *pos; |
910 | 1179 | struct dpp_authentication *auth = hapd->dpp_auth; |
911 | 1180 | enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED; |
1181 | int res; | |
912 | 1182 | |
913 | 1183 | if (!auth || !auth->auth_success) { |
914 | 1184 | wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); |
939 | 1209 | goto fail; |
940 | 1210 | } |
941 | 1211 | |
942 | if (dpp_conf_resp_rx(auth, resp) < 0) { | |
1212 | res = dpp_conf_resp_rx(auth, resp); | |
1213 | #ifdef CONFIG_DPP3 | |
1214 | if (res == -3) { | |
1215 | wpa_printf(MSG_DEBUG, "DPP: New protocol key needed"); | |
1216 | eloop_register_timeout(0, 0, hostapd_dpp_build_new_key, hapd, | |
1217 | NULL); | |
1218 | return; | |
1219 | } | |
1220 | #endif /* CONFIG_DPP3 */ | |
1221 | if (res < 0) { | |
943 | 1222 | wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); |
944 | 1223 | goto fail; |
945 | 1224 | } |
1574 | 1853 | } |
1575 | 1854 | #endif /* CONFIG_DPP3 */ |
1576 | 1855 | |
1856 | #ifdef CONFIG_TESTING_OPTIONS | |
1857 | if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP) { | |
1858 | wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version"); | |
1859 | ver = 1; | |
1860 | } | |
1861 | #endif /* CONFIG_TESTING_OPTIONS */ | |
1862 | ||
1577 | 1863 | /* Protocol Version */ |
1578 | 1864 | wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); |
1579 | 1865 | wpabuf_put_le16(msg, 1); |
1711 | 1997 | |
1712 | 1998 | static void |
1713 | 1999 | hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src, |
1714 | const u8 *buf, size_t len, | |
2000 | const u8 *hdr, const u8 *buf, size_t len, | |
1715 | 2001 | unsigned int freq, bool v2) |
1716 | 2002 | { |
1717 | 2003 | struct wpabuf *msg; |
1719 | 2005 | wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR, |
1720 | 2006 | MAC2STR(src)); |
1721 | 2007 | |
2008 | if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) { | |
2009 | wpa_printf(MSG_DEBUG, | |
2010 | "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only"); | |
2011 | return; | |
2012 | } | |
2013 | if (hapd->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) { | |
2014 | wpa_printf(MSG_DEBUG, | |
2015 | "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only"); | |
2016 | return; | |
2017 | } | |
2018 | ||
1722 | 2019 | /* TODO: Support multiple PKEX codes by iterating over all the enabled |
1723 | 2020 | * values here */ |
1724 | 2021 | |
1725 | 2022 | if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) { |
1726 | 2023 | wpa_printf(MSG_DEBUG, |
1727 | 2024 | "DPP: No PKEX code configured - ignore request"); |
1728 | return; | |
2025 | goto try_relay; | |
1729 | 2026 | } |
1730 | 2027 | |
1731 | 2028 | if (hapd->dpp_pkex) { |
1732 | 2029 | /* TODO: Support parallel operations */ |
1733 | 2030 | wpa_printf(MSG_DEBUG, |
1734 | 2031 | "DPP: Already in PKEX session - ignore new request"); |
1735 | return; | |
2032 | goto try_relay; | |
1736 | 2033 | } |
1737 | 2034 | |
1738 | 2035 | hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx, |
1744 | 2041 | if (!hapd->dpp_pkex) { |
1745 | 2042 | wpa_printf(MSG_DEBUG, |
1746 | 2043 | "DPP: Failed to process the request - ignore it"); |
1747 | return; | |
2044 | goto try_relay; | |
1748 | 2045 | } |
1749 | 2046 | |
1750 | 2047 | msg = hapd->dpp_pkex->exchange_resp; |
1761 | 2058 | dpp_pkex_free(hapd->dpp_pkex); |
1762 | 2059 | hapd->dpp_pkex = NULL; |
1763 | 2060 | } |
2061 | ||
2062 | return; | |
2063 | ||
2064 | try_relay: | |
2065 | #ifdef CONFIG_DPP2 | |
2066 | if (v2) | |
2067 | dpp_relay_rx_action(hapd->iface->interfaces->dpp, | |
2068 | src, hdr, buf, len, freq, NULL, NULL, hapd); | |
2069 | #else /* CONFIG_DPP2 */ | |
2070 | wpa_printf(MSG_DEBUG, "DPP: No relay functionality included - skip"); | |
2071 | #endif /* CONFIG_DPP2 */ | |
1764 | 2072 | } |
1765 | 2073 | |
1766 | 2074 | |
1781 | 2089 | wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); |
1782 | 2090 | return; |
1783 | 2091 | } |
2092 | ||
2093 | eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL); | |
2094 | hapd->dpp_pkex->exch_req_wait_time = 0; | |
1784 | 2095 | |
1785 | 2096 | msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, src, buf, len); |
1786 | 2097 | if (!msg) { |
1957 | 2268 | /* This is for PKEXv2, but for now, process only with |
1958 | 2269 | * CONFIG_DPP3 to avoid issues with a capability that has not |
1959 | 2270 | * been tested with other implementations. */ |
1960 | hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq, | |
2271 | hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq, | |
1961 | 2272 | true); |
1962 | 2273 | break; |
1963 | 2274 | #endif /* CONFIG_DPP3 */ |
1964 | 2275 | case DPP_PA_PKEX_V1_EXCHANGE_REQ: |
1965 | hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq, | |
2276 | hostapd_dpp_rx_pkex_exchange_req(hapd, src, hdr, buf, len, freq, | |
1966 | 2277 | false); |
1967 | 2278 | break; |
1968 | 2279 | case DPP_PA_PKEX_EXCHANGE_RESP: |
2068 | 2379 | if (!auth) |
2069 | 2380 | return; |
2070 | 2381 | |
2382 | #ifdef CONFIG_DPP3 | |
2383 | if (auth->waiting_new_key && ok) { | |
2384 | wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key"); | |
2385 | return; | |
2386 | } | |
2387 | #endif /* CONFIG_DPP3 */ | |
2388 | ||
2071 | 2389 | wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)", |
2072 | 2390 | ok); |
2073 | 2391 | eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); |
2128 | 2446 | { |
2129 | 2447 | struct dpp_bootstrap_info *own_bi; |
2130 | 2448 | const char *pos, *end; |
2449 | #ifdef CONFIG_DPP3 | |
2450 | enum dpp_pkex_ver ver = PKEX_VER_AUTO; | |
2451 | #else /* CONFIG_DPP3 */ | |
2452 | enum dpp_pkex_ver ver = PKEX_VER_ONLY_1; | |
2453 | #endif /* CONFIG_DPP3 */ | |
2454 | int tcp_port = DPP_TCP_PORT; | |
2455 | struct hostapd_ip_addr *ipaddr = NULL; | |
2456 | #ifdef CONFIG_DPP2 | |
2457 | struct hostapd_ip_addr ipaddr_buf; | |
2458 | char *addr; | |
2459 | ||
2460 | pos = os_strstr(cmd, " tcp_port="); | |
2461 | if (pos) { | |
2462 | pos += 10; | |
2463 | tcp_port = atoi(pos); | |
2464 | } | |
2465 | ||
2466 | addr = get_param(cmd, " tcp_addr="); | |
2467 | if (addr) { | |
2468 | int res; | |
2469 | ||
2470 | res = hostapd_parse_ip_addr(addr, &ipaddr_buf); | |
2471 | os_free(addr); | |
2472 | if (res) | |
2473 | return -1; | |
2474 | ipaddr = &ipaddr_buf; | |
2475 | } | |
2476 | #endif /* CONFIG_DPP2 */ | |
2131 | 2477 | |
2132 | 2478 | pos = os_strstr(cmd, " own="); |
2133 | 2479 | if (!pos) |
2170 | 2516 | if (!hapd->dpp_pkex_code) |
2171 | 2517 | return -1; |
2172 | 2518 | |
2173 | if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) { | |
2174 | struct wpabuf *msg; | |
2175 | bool v2 = os_strstr(cmd, " init=2") != NULL; | |
2176 | ||
2177 | wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX"); | |
2178 | dpp_pkex_free(hapd->dpp_pkex); | |
2179 | hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi, | |
2180 | hapd->own_addr, | |
2181 | hapd->dpp_pkex_identifier, | |
2182 | hapd->dpp_pkex_code, v2); | |
2183 | if (!hapd->dpp_pkex) | |
2519 | pos = os_strstr(cmd, " ver="); | |
2520 | if (pos) { | |
2521 | int v; | |
2522 | ||
2523 | pos += 5; | |
2524 | v = atoi(pos); | |
2525 | if (v == 1) | |
2526 | ver = PKEX_VER_ONLY_1; | |
2527 | else if (v == 2) | |
2528 | ver = PKEX_VER_ONLY_2; | |
2529 | else | |
2184 | 2530 | return -1; |
2185 | ||
2186 | msg = hapd->dpp_pkex->exchange_req; | |
2187 | /* TODO: Which channel to use? */ | |
2188 | wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR | |
2189 | " freq=%u type=%d", MAC2STR(broadcast), 2437, | |
2190 | v2 ? DPP_PA_PKEX_EXCHANGE_REQ : | |
2191 | DPP_PA_PKEX_V1_EXCHANGE_REQ); | |
2192 | hostapd_drv_send_action(hapd, 2437, 0, broadcast, | |
2193 | wpabuf_head(msg), wpabuf_len(msg)); | |
2531 | } | |
2532 | hapd->dpp_pkex_ver = ver; | |
2533 | ||
2534 | if (os_strstr(cmd, " init=1")) { | |
2535 | if (hostapd_dpp_pkex_init(hapd, ver, ipaddr, tcp_port) < 0) | |
2536 | return -1; | |
2537 | } else { | |
2538 | #ifdef CONFIG_DPP2 | |
2539 | dpp_controller_pkex_add(hapd->iface->interfaces->dpp, own_bi, | |
2540 | hapd->dpp_pkex_code, | |
2541 | hapd->dpp_pkex_identifier); | |
2542 | #endif /* CONFIG_DPP2 */ | |
2194 | 2543 | } |
2195 | 2544 | |
2196 | 2545 | /* TODO: Support multiple PKEX info entries */ |
2318 | 2667 | #endif /* CONFIG_TESTING_OPTIONS */ |
2319 | 2668 | if (!hapd->dpp_init_done) |
2320 | 2669 | return; |
2670 | eloop_cancel_timeout(hostapd_dpp_pkex_retry_timeout, hapd, NULL); | |
2321 | 2671 | eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); |
2322 | 2672 | eloop_cancel_timeout(hostapd_dpp_auth_conf_wait_timeout, hapd, NULL); |
2323 | 2673 | eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); |
2333 | 2683 | if (hapd->iface->interfaces) |
2334 | 2684 | dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd); |
2335 | 2685 | #endif /* CONFIG_DPP2 */ |
2686 | #ifdef CONFIG_DPP3 | |
2687 | eloop_cancel_timeout(hostapd_dpp_build_new_key, hapd, NULL); | |
2688 | #endif /* CONFIG_DPP3 */ | |
2336 | 2689 | dpp_auth_deinit(hapd->dpp_auth); |
2337 | 2690 | hapd->dpp_auth = NULL; |
2338 | 2691 | hostapd_dpp_pkex_remove(hapd, "*"); |
260 | 260 | } |
261 | 261 | #endif /* NEED_AP_MLME */ |
262 | 262 | |
263 | #ifdef CONFIG_INTERWORKING | |
264 | if (elems.ext_capab && elems.ext_capab_len > 4) { | |
265 | if (elems.ext_capab[4] & 0x01) | |
266 | sta->qos_map_enabled = 1; | |
267 | } | |
268 | #endif /* CONFIG_INTERWORKING */ | |
263 | check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len); | |
269 | 264 | |
270 | 265 | #ifdef CONFIG_HS20 |
271 | 266 | wpabuf_free(sta->hs20_ie); |
1010 | 1005 | hostapd_neighbor_set_own_report(hapd->iface->bss[i]); |
1011 | 1006 | |
1012 | 1007 | #ifdef CONFIG_OCV |
1013 | if (hapd->conf->ocv) { | |
1008 | if (hapd->conf->ocv && | |
1009 | !(hapd->iface->drv_flags2 & | |
1010 | WPA_DRIVER_FLAGS2_SA_QUERY_OFFLOAD_AP)) { | |
1014 | 1011 | struct sta_info *sta; |
1015 | 1012 | bool check_sa_query = false; |
1016 | 1013 |
1457 | 1457 | } |
1458 | 1458 | |
1459 | 1459 | |
1460 | static void hostapd_set_acl(struct hostapd_data *hapd) | |
1460 | int hostapd_set_acl(struct hostapd_data *hapd) | |
1461 | 1461 | { |
1462 | 1462 | struct hostapd_config *conf = hapd->iconf; |
1463 | int err; | |
1463 | int err = 0; | |
1464 | 1464 | u8 accept_acl; |
1465 | 1465 | |
1466 | 1466 | if (hapd->iface->drv_max_acl_mac_addrs == 0) |
1467 | return; | |
1467 | return 0; | |
1468 | 1468 | |
1469 | 1469 | if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) { |
1470 | 1470 | accept_acl = 1; |
1473 | 1473 | accept_acl); |
1474 | 1474 | if (err) { |
1475 | 1475 | wpa_printf(MSG_DEBUG, "Failed to set accept acl"); |
1476 | return; | |
1476 | return -1; | |
1477 | 1477 | } |
1478 | 1478 | } else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) { |
1479 | 1479 | accept_acl = 0; |
1482 | 1482 | accept_acl); |
1483 | 1483 | if (err) { |
1484 | 1484 | wpa_printf(MSG_DEBUG, "Failed to set deny acl"); |
1485 | return; | |
1486 | } | |
1487 | } | |
1485 | return -1; | |
1486 | } | |
1487 | } | |
1488 | return err; | |
1488 | 1489 | } |
1489 | 1490 | |
1490 | 1491 |
13 | 13 | #endif /* CONFIG_SQLITE */ |
14 | 14 | |
15 | 15 | #include "common/defs.h" |
16 | #include "common/dpp.h" | |
16 | 17 | #include "utils/list.h" |
17 | 18 | #include "ap_config.h" |
18 | 19 | #include "drivers/driver.h" |
387 | 388 | struct dpp_bootstrap_info *dpp_pkex_bi; |
388 | 389 | char *dpp_pkex_code; |
389 | 390 | char *dpp_pkex_identifier; |
391 | enum dpp_pkex_ver dpp_pkex_ver; | |
390 | 392 | char *dpp_pkex_auth_cmd; |
391 | 393 | char *dpp_configurator_params; |
392 | 394 | struct os_reltime dpp_last_init; |
518 | 520 | struct hostapd_rate_data *current_rates; |
519 | 521 | int *basic_rates; |
520 | 522 | int freq; |
523 | ||
524 | /* Background radar configuration */ | |
525 | struct { | |
526 | int channel; | |
527 | int secondary_channel; | |
528 | int freq; | |
529 | int centr_freq_seg0_idx; | |
530 | int centr_freq_seg1_idx; | |
531 | /* Main chain is on temporary channel during | |
532 | * CAC detection on radar offchain. | |
533 | */ | |
534 | unsigned int temp_ch:1; | |
535 | /* CAC started on radar offchain */ | |
536 | unsigned int cac_started:1; | |
537 | } radar_background; | |
521 | 538 | |
522 | 539 | u16 hw_flags; |
523 | 540 | |
691 | 708 | struct fst_wpa_obj *iface_obj); |
692 | 709 | #endif /* CONFIG_FST */ |
693 | 710 | |
711 | int hostapd_set_acl(struct hostapd_data *hapd); | |
712 | ||
694 | 713 | #endif /* HOSTAPD_H */ |
497 | 497 | struct sae_password_entry *pw; |
498 | 498 | struct sae_pt *pt = NULL; |
499 | 499 | const struct sae_pk *pk = NULL; |
500 | struct hostapd_sta_wpa_psk_short *psk = NULL; | |
500 | 501 | |
501 | 502 | for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) { |
502 | 503 | if (!is_broadcast_ether_addr(pw->peer_addr) && |
516 | 517 | if (!password) { |
517 | 518 | password = hapd->conf->ssid.wpa_passphrase; |
518 | 519 | pt = hapd->conf->ssid.pt; |
520 | } | |
521 | ||
522 | if (!password) { | |
523 | for (psk = sta->psk; psk; psk = psk->next) { | |
524 | if (psk->is_passphrase) { | |
525 | password = psk->passphrase; | |
526 | break; | |
527 | } | |
528 | } | |
519 | 529 | } |
520 | 530 | |
521 | 531 | if (pw_entry) |
4122 | 4132 | } |
4123 | 4133 | |
4124 | 4134 | |
4125 | static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta, | |
4126 | const u8 *ext_capab_ie, size_t ext_capab_ie_len) | |
4127 | { | |
4128 | #ifdef CONFIG_INTERWORKING | |
4129 | /* check for QoS Map support */ | |
4130 | if (ext_capab_ie_len >= 5) { | |
4131 | if (ext_capab_ie[4] & 0x01) | |
4132 | sta->qos_map_enabled = 1; | |
4133 | } | |
4134 | #endif /* CONFIG_INTERWORKING */ | |
4135 | ||
4136 | if (ext_capab_ie_len > 0) { | |
4137 | sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2)); | |
4138 | os_free(sta->ext_capability); | |
4139 | sta->ext_capability = os_malloc(1 + ext_capab_ie_len); | |
4140 | if (sta->ext_capability) { | |
4141 | sta->ext_capability[0] = ext_capab_ie_len; | |
4142 | os_memcpy(sta->ext_capability + 1, ext_capab_ie, | |
4143 | ext_capab_ie_len); | |
4144 | } | |
4145 | } | |
4146 | ||
4147 | return WLAN_STATUS_SUCCESS; | |
4148 | } | |
4149 | ||
4150 | ||
4151 | 4135 | #ifdef CONFIG_OWE |
4152 | 4136 | |
4153 | 4137 | static int owe_group_supported(struct hostapd_data *hapd, u16 group) |
6097 | 6081 | end = ((const u8 *) mgmt) + len; |
6098 | 6082 | gas_query_ap_rx(hapd->gas, mgmt->sa, |
6099 | 6083 | mgmt->u.action.category, |
6100 | pos, end - pos, hapd->iface->freq); | |
6084 | pos, end - pos, freq); | |
6101 | 6085 | return 1; |
6102 | 6086 | } |
6103 | 6087 | #endif /* CONFIG_DPP */ |
6104 | 6088 | if (hapd->public_action_cb) { |
6105 | 6089 | hapd->public_action_cb(hapd->public_action_cb_ctx, |
6106 | (u8 *) mgmt, len, | |
6107 | hapd->iface->freq); | |
6090 | (u8 *) mgmt, len, freq); | |
6108 | 6091 | } |
6109 | 6092 | if (hapd->public_action_cb2) { |
6110 | 6093 | hapd->public_action_cb2(hapd->public_action_cb2_ctx, |
6111 | (u8 *) mgmt, len, | |
6112 | hapd->iface->freq); | |
6094 | (u8 *) mgmt, len, freq); | |
6113 | 6095 | } |
6114 | 6096 | if (hapd->public_action_cb || hapd->public_action_cb2) |
6115 | 6097 | return 1; |
6117 | 6099 | case WLAN_ACTION_VENDOR_SPECIFIC: |
6118 | 6100 | if (hapd->vendor_action_cb) { |
6119 | 6101 | if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx, |
6120 | (u8 *) mgmt, len, | |
6121 | hapd->iface->freq) == 0) | |
6102 | (u8 *) mgmt, len, freq) == 0) | |
6122 | 6103 | return 1; |
6123 | 6104 | } |
6124 | 6105 | break; |
6620 | 6601 | struct sta_info *sta; |
6621 | 6602 | const struct rrm_measurement_report_element *report; |
6622 | 6603 | |
6623 | if (is_multicast_ether_addr(mgmt->da)) | |
6624 | return; | |
6625 | 6604 | #ifdef CONFIG_DPP |
6626 | 6605 | if (len >= IEEE80211_HDRLEN + 6 && |
6627 | 6606 | mgmt->u.action.category == WLAN_ACTION_PUBLIC && |
6652 | 6631 | return; |
6653 | 6632 | } |
6654 | 6633 | #endif /* CONFIG_DPP */ |
6634 | if (is_multicast_ether_addr(mgmt->da)) | |
6635 | return; | |
6655 | 6636 | sta = ap_get_sta(hapd, mgmt->da); |
6656 | 6637 | if (!sta) { |
6657 | 6638 | wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR |
193 | 193 | |
194 | 194 | void auth_sae_process_commit(void *eloop_ctx, void *user_ctx); |
195 | 195 | u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len); |
196 | u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta, | |
197 | const u8 *ext_capab_ie, size_t ext_capab_ie_len); | |
196 | 198 | size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type); |
197 | 199 | u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type); |
198 | 200 |
645 | 645 | while (psk) { |
646 | 646 | struct hostapd_sta_wpa_psk_short *prev = psk; |
647 | 647 | psk = psk->next; |
648 | os_free(prev); | |
649 | } | |
650 | } | |
648 | bin_clear_free(prev, sizeof(*prev)); | |
649 | } | |
650 | } |
28 | 28 | |
29 | 29 | ru = (ppe_thres_hdr >> HE_PPE_THRES_RU_INDEX_BITMASK_SHIFT) & |
30 | 30 | HE_PPE_THRES_RU_INDEX_BITMASK_MASK; |
31 | /* Count the number of 1 bits in RU Index Bitmask */ | |
31 | 32 | while (ru) { |
32 | 33 | if (ru & 0x1) |
33 | 34 | sz++; |
34 | 35 | ru >>= 1; |
35 | 36 | } |
36 | 37 | |
38 | /* fixed header of 3 (NSTS) + 4 (RU Index Bitmask) = 7 bits */ | |
39 | /* 6 * (NSTS + 1) bits for bit 1 in RU Index Bitmask */ | |
37 | 40 | sz *= 1 + (ppe_thres_hdr & HE_PPE_THRES_NSS_MASK); |
38 | 41 | sz = (sz * 6) + 7; |
39 | if (sz % 8) | |
40 | sz += 8; | |
41 | sz /= 8; | |
42 | /* PPE Pad to count the number of needed full octets */ | |
43 | sz = (sz + 7) / 8; | |
42 | 44 | |
43 | 45 | return sz; |
44 | 46 | } |
63 | 65 | { |
64 | 66 | struct ieee80211_he_capabilities *cap; |
65 | 67 | size_t cap_len; |
68 | u8 ppe_thres_hdr; | |
66 | 69 | |
67 | 70 | cap = (struct ieee80211_he_capabilities *) buf; |
68 | 71 | cap_len = sizeof(*cap) - sizeof(cap->optional); |
73 | 76 | if (len < cap_len) |
74 | 77 | return 1; |
75 | 78 | |
76 | cap_len += ieee80211_he_ppet_size(buf[cap_len], cap->he_phy_capab_info); | |
77 | ||
78 | return len != cap_len; | |
79 | ppe_thres_hdr = len > cap_len ? buf[cap_len] : 0xff; | |
80 | cap_len += ieee80211_he_ppet_size(ppe_thres_hdr, | |
81 | cap->he_phy_capab_info); | |
82 | ||
83 | return len < cap_len; | |
79 | 84 | } |
80 | 85 | |
81 | 86 |
1092 | 1092 | |
1093 | 1093 | return pos; |
1094 | 1094 | } |
1095 | ||
1096 | ||
1097 | u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta, | |
1098 | const u8 *ext_capab_ie, size_t ext_capab_ie_len) | |
1099 | { | |
1100 | #ifdef CONFIG_INTERWORKING | |
1101 | /* check for QoS Map support */ | |
1102 | if (ext_capab_ie_len >= 5) { | |
1103 | if (ext_capab_ie[4] & 0x01) | |
1104 | sta->qos_map_enabled = 1; | |
1105 | } | |
1106 | #endif /* CONFIG_INTERWORKING */ | |
1107 | ||
1108 | if (ext_capab_ie_len > 0) { | |
1109 | sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2)); | |
1110 | os_free(sta->ext_capability); | |
1111 | sta->ext_capability = os_malloc(1 + ext_capab_ie_len); | |
1112 | if (sta->ext_capability) { | |
1113 | sta->ext_capability[0] = ext_capab_ie_len; | |
1114 | os_memcpy(sta->ext_capability + 1, ext_capab_ie, | |
1115 | ext_capab_ie_len); | |
1116 | } | |
1117 | } | |
1118 | ||
1119 | return WLAN_STATUS_SUCCESS; | |
1120 | } |
409 | 409 | |
410 | 410 | #ifdef CONFIG_TESTING_OPTIONS |
411 | 411 | os_free(sta->sae_postponed_commit); |
412 | forced_memzero(sta->last_tk, WPA_TK_MAX_LEN); | |
412 | 413 | #endif /* CONFIG_TESTING_OPTIONS */ |
413 | 414 | |
414 | 415 | os_free(sta); |
1250 | 1251 | for (psk = ssid->wpa_psk; psk; psk = psk->next) |
1251 | 1252 | if (os_memcmp(pmk, psk->psk, PMK_LEN) == 0) |
1252 | 1253 | break; |
1253 | if (!psk) | |
1254 | return NULL; | |
1255 | 1254 | if (!psk || !psk->keyid[0]) |
1256 | 1255 | return NULL; |
1257 | 1256 |
408 | 408 | u8 dialog_token, reason; |
409 | 409 | const u8 *pos, *end; |
410 | 410 | int enabled = hapd->conf->bss_transition; |
411 | char *hex = NULL; | |
412 | size_t hex_len; | |
411 | 413 | |
412 | 414 | #ifdef CONFIG_MBO |
413 | 415 | if (hapd->conf->mbo_enabled) |
439 | 441 | |
440 | 442 | wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", |
441 | 443 | pos, end - pos); |
444 | ||
445 | hex_len = 2 * (end - pos) + 1; | |
446 | if (hex_len > 1) { | |
447 | hex = os_malloc(hex_len); | |
448 | if (hex) | |
449 | wpa_snprintf_hex(hex, hex_len, pos, end - pos); | |
450 | } | |
451 | wpa_msg(hapd->msg_ctx, MSG_INFO, | |
452 | BSS_TM_QUERY MACSTR " reason=%u%s%s", | |
453 | MAC2STR(addr), reason, hex ? " neighbor=" : "", hex); | |
454 | os_free(hex); | |
442 | 455 | |
443 | 456 | ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token); |
444 | 457 | } |
602 | 602 | while (group) { |
603 | 603 | prev = group; |
604 | 604 | group = group->next; |
605 | os_free(prev); | |
605 | bin_clear_free(prev, sizeof(*prev)); | |
606 | 606 | } |
607 | 607 | |
608 | 608 | os_free(wpa_auth); |
1641 | 1641 | if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, |
1642 | 1642 | (key_data_len - 8) / 8, buf, key_data)) { |
1643 | 1643 | os_free(hdr); |
1644 | os_free(buf); | |
1644 | bin_clear_free(buf, key_data_len); | |
1645 | 1645 | return; |
1646 | 1646 | } |
1647 | 1647 | WPA_PUT_BE16(key_mic + mic_len, key_data_len); |
1662 | 1662 | #endif /* CONFIG_NO_RC4 */ |
1663 | 1663 | } else { |
1664 | 1664 | os_free(hdr); |
1665 | os_free(buf); | |
1665 | bin_clear_free(buf, key_data_len); | |
1666 | 1666 | return; |
1667 | 1667 | } |
1668 | os_free(buf); | |
1668 | bin_clear_free(buf, key_data_len); | |
1669 | 1669 | } |
1670 | 1670 | |
1671 | 1671 | if (key_info & WPA_KEY_INFO_MIC) { |
1813 | 1813 | case WPA_DEAUTH: |
1814 | 1814 | case WPA_DISASSOC: |
1815 | 1815 | sm->DeauthenticationRequest = true; |
1816 | #ifdef CONFIG_IEEE80211R_AP | |
1817 | 1816 | os_memset(sm->PMK, 0, sizeof(sm->PMK)); |
1818 | 1817 | sm->pmk_len = 0; |
1818 | #ifdef CONFIG_IEEE80211R_AP | |
1819 | 1819 | os_memset(sm->xxkey, 0, sizeof(sm->xxkey)); |
1820 | 1820 | sm->xxkey_len = 0; |
1821 | 1821 | os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1)); |
3269 | 3269 | pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, |
3270 | 3270 | (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, |
3271 | 3271 | NULL, 0); |
3272 | forced_memzero(&igtk, sizeof(igtk)); | |
3272 | 3273 | |
3273 | 3274 | if (!conf->beacon_prot) |
3274 | 3275 | return pos; |
3292 | 3293 | pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK, |
3293 | 3294 | (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len, |
3294 | 3295 | NULL, 0); |
3296 | forced_memzero(&bigtk, sizeof(bigtk)); | |
3295 | 3297 | |
3296 | 3298 | return pos; |
3297 | 3299 | } |
3372 | 3374 | SM_STATE(WPA_PTK, PTKINITNEGOTIATING) |
3373 | 3375 | { |
3374 | 3376 | u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32]; |
3375 | size_t gtk_len, kde_len, wpa_ie_len; | |
3377 | size_t gtk_len, kde_len = 0, wpa_ie_len; | |
3376 | 3378 | struct wpa_group *gsm = sm->group; |
3377 | 3379 | u8 *wpa_ie; |
3378 | 3380 | int secure, gtkidx, encr = 0; |
3630 | 3632 | WPA_KEY_INFO_KEY_TYPE, |
3631 | 3633 | _rsc, sm->ANonce, kde, pos - kde, 0, encr); |
3632 | 3634 | done: |
3633 | os_free(kde); | |
3635 | bin_clear_free(kde, kde_len); | |
3634 | 3636 | os_free(wpa_ie_buf); |
3635 | 3637 | os_free(wpa_ie_buf2); |
3636 | 3638 | } |
3851 | 3853 | struct wpa_group *gsm = sm->group; |
3852 | 3854 | const u8 *kde; |
3853 | 3855 | u8 *kde_buf = NULL, *pos, hdr[2]; |
3854 | size_t kde_len; | |
3856 | size_t kde_len = 0; | |
3855 | 3857 | u8 *gtk, stub_gtk[32]; |
3856 | 3858 | struct wpa_auth_config *conf = &sm->wpa_auth->conf; |
3857 | 3859 | |
3920 | 3922 | (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), |
3921 | 3923 | rsc, NULL, kde, kde_len, gsm->GN, 1); |
3922 | 3924 | |
3923 | os_free(kde_buf); | |
3925 | bin_clear_free(kde_buf, kde_len); | |
3924 | 3926 | } |
3925 | 3927 | |
3926 | 3928 | |
5562 | 5564 | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | |
5563 | 5565 | WPA_KEY_INFO_KEY_TYPE, |
5564 | 5566 | _rsc, sm->ANonce, kde, pos - kde, 0, encr); |
5565 | os_free(kde); | |
5567 | bin_clear_free(kde, kde_len); | |
5566 | 5568 | return 0; |
5567 | 5569 | } |
5568 | 5570 | |
5630 | 5632 | (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), |
5631 | 5633 | rsc, NULL, kde, kde_len, gsm->GN, 1); |
5632 | 5634 | |
5633 | os_free(kde_buf); | |
5635 | bin_clear_free(kde_buf, kde_len); | |
5634 | 5636 | return 0; |
5635 | 5637 | } |
5636 | 5638 |
2239 | 2239 | wpa_printf(MSG_DEBUG, |
2240 | 2240 | "FT: GTK subelem encryption failed: kek_len=%d", |
2241 | 2241 | (int) kek_len); |
2242 | forced_memzero(keybuf, sizeof(keybuf)); | |
2242 | 2243 | os_free(subelem); |
2243 | 2244 | return NULL; |
2244 | 2245 | } |
1630 | 1630 | hapd->l2 = NULL; |
1631 | 1631 | hostapd_wpa_unregister_ft_oui(hapd); |
1632 | 1632 | #endif /* CONFIG_IEEE80211R_AP */ |
1633 | } | |
1633 | ||
1634 | #ifdef CONFIG_TESTING_OPTIONS | |
1635 | forced_memzero(hapd->last_gtk, WPA_GTK_MAX_LEN); | |
1636 | forced_memzero(hapd->last_igtk, WPA_IGTK_MAX_LEN); | |
1637 | forced_memzero(hapd->last_bigtk, WPA_BIGTK_MAX_LEN); | |
1638 | #endif /* CONFIG_TESTING_OPTIONS */ | |
1639 | } |
137 | 137 | switch (co) { |
138 | 138 | case CONFIDENTIALITY_OFFSET_30: |
139 | 139 | return 30; |
140 | break; | |
141 | 140 | case CONFIDENTIALITY_OFFSET_50: |
142 | 141 | return 50; |
143 | 142 | default: |
328 | 327 | hapd->conf->macsec_replay_protect, |
329 | 328 | hapd->conf->macsec_replay_window, |
330 | 329 | hapd->conf->macsec_port, |
331 | hapd->conf->mka_priority, hapd->conf->iface, | |
330 | hapd->conf->mka_priority, | |
331 | hapd->conf->macsec_csindex, | |
332 | hapd->conf->iface, | |
332 | 333 | hapd->own_addr); |
333 | 334 | /* ieee802_1x_kay_init() frees kay_ctx on failure */ |
334 | 335 | if (!res) |
1068 | 1068 | for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) |
1069 | 1069 | wpabuf_free(wps->dev.vendor_ext[i]); |
1070 | 1070 | wps_device_data_free(&wps->dev); |
1071 | os_free(wps->network_key); | |
1071 | bin_clear_free(wps->network_key, wps->network_key_len); | |
1072 | 1072 | hostapd_wps_nfc_clear(wps); |
1073 | 1073 | wpabuf_free(wps->dh_pubkey); |
1074 | 1074 | wpabuf_free(wps->dh_privkey); |
1075 | forced_memzero(wps->psk, sizeof(wps->psk)); | |
1075 | 1076 | os_free(wps); |
1076 | 1077 | } |
1077 | 1078 |
39 | 39 | * @BRCM_VENDOR_SCMD_SET_CONNECT_PARAMS: Set some connect parameters. |
40 | 40 | * Used for the case that FW handle SAE. |
41 | 41 | * |
42 | * @BRCM_VENDOR_SCMD_SET_START_AP_PARAMS: Set SoftAP paramters. | |
42 | * @BRCM_VENDOR_SCMD_SET_START_AP_PARAMS: Set SoftAP parameters. | |
43 | 43 | * Used for the case that FW handle SAE. |
44 | 44 | * |
45 | 45 | * @BRCM_VENDOR_SCMD_ACS: ACS command/event which is used to |
46 | 46 | * invoke the ACS function in device and pass selected channels to |
47 | 47 | * hostapd. Uses enum qca_wlan_vendor_attr_acs_offload attributes. |
48 | 48 | * |
49 | * @BRCM_VENDOR_SCMD_MAX: This acts as a the tail of cmds list. | |
50 | * Make sure it located at the end of the list. | |
49 | * @BRCM_VENDOR_SCMD_MAX: This acts as a tail of cmds list. | |
50 | * Make sure it is located at the end of the list. | |
51 | 51 | * |
52 | 52 | */ |
53 | 53 | enum brcm_nl80211_vendor_subcmds { |
65 | 65 | }; |
66 | 66 | |
67 | 67 | /** |
68 | * enum brcm_nl80211_vendor_events - BRCM nl80211 asynchoronous event identifiers | |
68 | * enum brcm_nl80211_vendor_events - BRCM nl80211 asynchronous event identifiers | |
69 | 69 | * |
70 | 70 | * @BRCM_VENDOR_EVENT_UNSPEC: Reserved value 0 |
71 | 71 | * |
1 | 1 | * DPP functionality shared between hostapd and wpa_supplicant |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2018-2020, The Linux Foundation |
4 | * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
23 | 24 | #include "dpp.h" |
24 | 25 | #include "dpp_i.h" |
25 | 26 | |
26 | ||
27 | static const char * dpp_netrole_str(enum dpp_netrole netrole); | |
28 | 27 | |
29 | 28 | #ifdef CONFIG_TESTING_OPTIONS |
30 | 29 | #ifdef CONFIG_DPP3 |
658 | 657 | { |
659 | 658 | size_t nonce_len; |
660 | 659 | size_t json_len, clear_len; |
661 | struct wpabuf *clear = NULL, *msg = NULL; | |
660 | struct wpabuf *clear = NULL, *msg = NULL, *pe = NULL; | |
662 | 661 | u8 *wrapped; |
663 | 662 | size_t attr_len; |
663 | #ifdef CONFIG_DPP3 | |
664 | u8 auth_i[DPP_MAX_HASH_LEN]; | |
665 | #endif /* CONFIG_DPP3 */ | |
664 | 666 | |
665 | 667 | wpa_printf(MSG_DEBUG, "DPP: Build configuration request"); |
666 | 668 | |
675 | 677 | |
676 | 678 | /* { E-nonce, configAttrib }ke */ |
677 | 679 | clear_len = 4 + nonce_len + 4 + json_len; |
680 | #ifdef CONFIG_DPP3 | |
681 | if (auth->waiting_new_key) { | |
682 | pe = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); | |
683 | if (!pe) | |
684 | goto fail; | |
685 | clear_len += 4 + wpabuf_len(pe); | |
686 | ||
687 | if (dpp_derive_auth_i(auth, auth_i) < 0) | |
688 | goto fail; | |
689 | clear_len += 4 + auth->curve->hash_len; | |
690 | } | |
691 | #endif /* CONFIG_DPP3 */ | |
678 | 692 | clear = wpabuf_alloc(clear_len); |
679 | 693 | attr_len = 4 + clear_len + AES_BLOCK_SIZE; |
680 | 694 | #ifdef CONFIG_TESTING_OPTIONS |
716 | 730 | } |
717 | 731 | #endif /* CONFIG_TESTING_OPTIONS */ |
718 | 732 | |
733 | #ifdef CONFIG_DPP3 | |
734 | if (pe) { | |
735 | wpa_printf(MSG_DEBUG, "DPP: Pe"); | |
736 | wpabuf_put_le16(clear, DPP_ATTR_I_PROTOCOL_KEY); | |
737 | wpabuf_put_le16(clear, wpabuf_len(pe)); | |
738 | wpabuf_put_buf(clear, pe); | |
739 | } | |
740 | if (auth->waiting_new_key) { | |
741 | wpa_printf(MSG_DEBUG, "DPP: Initiator Authentication Tag"); | |
742 | wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); | |
743 | wpabuf_put_le16(clear, auth->curve->hash_len); | |
744 | wpabuf_put_data(clear, auth_i, auth->curve->hash_len); | |
745 | } | |
746 | #endif /* CONFIG_DPP3 */ | |
747 | ||
719 | 748 | /* configAttrib */ |
720 | 749 | wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ); |
721 | 750 | wpabuf_put_le16(clear, json_len); |
748 | 777 | |
749 | 778 | wpa_hexdump_buf(MSG_DEBUG, |
750 | 779 | "DPP: Configuration Request frame attributes", msg); |
780 | out: | |
751 | 781 | wpabuf_free(clear); |
782 | wpabuf_free(pe); | |
752 | 783 | return msg; |
753 | 784 | |
754 | 785 | fail: |
755 | wpabuf_free(clear); | |
756 | 786 | wpabuf_free(msg); |
757 | return NULL; | |
787 | msg = NULL; | |
788 | goto out; | |
758 | 789 | } |
759 | 790 | |
760 | 791 | |
815 | 846 | size_t len, name_len; |
816 | 847 | const char *tech = "infra"; |
817 | 848 | const char *dpp_name; |
818 | struct wpabuf *buf, *json; | |
849 | struct wpabuf *buf = NULL, *json = NULL; | |
819 | 850 | char *csr = NULL; |
820 | 851 | |
821 | 852 | #ifdef CONFIG_TESTING_OPTIONS |
840 | 871 | csr = base64_encode_no_lf(wpabuf_head(auth->csr), |
841 | 872 | wpabuf_len(auth->csr), &csr_len); |
842 | 873 | if (!csr) |
843 | return NULL; | |
874 | goto fail; | |
844 | 875 | len += 30 + csr_len; |
845 | 876 | } |
846 | 877 | #endif /* CONFIG_DPP2 */ |
847 | 878 | json = wpabuf_alloc(len); |
848 | 879 | if (!json) |
849 | return NULL; | |
880 | goto fail; | |
850 | 881 | |
851 | 882 | json_start_object(json, NULL); |
852 | if (json_add_string_escape(json, "name", dpp_name, name_len) < 0) { | |
853 | wpabuf_free(json); | |
854 | return NULL; | |
855 | } | |
883 | if (json_add_string_escape(json, "name", dpp_name, name_len) < 0) | |
884 | goto fail; | |
856 | 885 | json_value_sep(json); |
857 | 886 | json_add_string(json, "wi-fi_tech", tech); |
858 | 887 | json_value_sep(json); |
877 | 906 | json_end_object(json); |
878 | 907 | |
879 | 908 | buf = dpp_build_conf_req(auth, wpabuf_head(json)); |
909 | fail: | |
880 | 910 | wpabuf_free(json); |
881 | 911 | os_free(csr); |
882 | 912 | |
1209 | 1239 | |
1210 | 1240 | wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd); |
1211 | 1241 | |
1242 | if (os_strstr(cmd, " conf=query")) { | |
1243 | auth->configurator_set = 0; | |
1244 | auth->use_config_query = true; | |
1245 | ret = 0; | |
1246 | goto fail; | |
1247 | } | |
1248 | ||
1212 | 1249 | pos = os_strstr(cmd, " configurator="); |
1213 | 1250 | if (!auth->conf && pos) { |
1214 | 1251 | pos += 14; |
1289 | 1326 | dl_list_del(&auth->tmp_peer_bi->list); |
1290 | 1327 | dpp_bootstrap_info_free(auth->tmp_peer_bi); |
1291 | 1328 | } |
1329 | os_free(auth->e_name); | |
1330 | os_free(auth->e_mud_url); | |
1331 | os_free(auth->e_band_support); | |
1292 | 1332 | #ifdef CONFIG_TESTING_OPTIONS |
1293 | 1333 | os_free(auth->config_obj_override); |
1294 | 1334 | os_free(auth->discovery_override); |
1399 | 1439 | } |
1400 | 1440 | |
1401 | 1441 | |
1402 | static const char * dpp_netrole_str(enum dpp_netrole netrole) | |
1442 | const char * dpp_netrole_str(enum dpp_netrole netrole) | |
1403 | 1443 | { |
1404 | 1444 | switch (netrole) { |
1405 | 1445 | case DPP_NETROLE_STA: |
1421 | 1461 | struct wpabuf *buf = NULL; |
1422 | 1462 | char *signed_conn = NULL; |
1423 | 1463 | size_t tailroom; |
1424 | const struct dpp_curve_params *curve; | |
1464 | const struct dpp_curve_params *curve; /* C-sign-key curve */ | |
1465 | const struct dpp_curve_params *nak_curve; /* netAccessKey curve */ | |
1425 | 1466 | struct wpabuf *dppcon = NULL; |
1426 | 1467 | size_t extra_len = 1000; |
1427 | 1468 | int incl_legacy; |
1434 | 1475 | goto fail; |
1435 | 1476 | } |
1436 | 1477 | curve = auth->conf->curve; |
1478 | if (auth->new_curve && auth->new_key_received) | |
1479 | nak_curve = auth->new_curve; | |
1480 | else | |
1481 | nak_curve = auth->curve; | |
1437 | 1482 | |
1438 | 1483 | akm = conf->akm; |
1439 | 1484 | if (dpp_akm_ver2(akm) && auth->peer_version < 2) { |
1451 | 1496 | extra_len += os_strlen(conf->group_id); |
1452 | 1497 | |
1453 | 1498 | /* Connector (JSON dppCon object) */ |
1454 | dppcon = wpabuf_alloc(extra_len + 2 * auth->curve->prime_len * 4 / 3); | |
1499 | dppcon = wpabuf_alloc(extra_len + 2 * nak_curve->prime_len * 4 / 3); | |
1455 | 1500 | if (!dppcon) |
1456 | 1501 | goto fail; |
1457 | 1502 | #ifdef CONFIG_TESTING_OPTIONS |
1481 | 1526 | #ifdef CONFIG_TESTING_OPTIONS |
1482 | 1527 | skip_groups: |
1483 | 1528 | #endif /* CONFIG_TESTING_OPTIONS */ |
1484 | if (!auth->peer_protocol_key || | |
1485 | dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, | |
1486 | auth->curve) < 0) { | |
1529 | if (!auth->peer_protocol_key) { | |
1530 | wpa_printf(MSG_DEBUG, | |
1531 | "DPP: No peer protocol key available to build netAccessKey JWK"); | |
1532 | goto fail; | |
1533 | } | |
1534 | #ifdef CONFIG_DPP3 | |
1535 | if (auth->conf->net_access_key_curve && | |
1536 | auth->curve != auth->conf->net_access_key_curve && | |
1537 | !auth->new_key_received) { | |
1538 | wpa_printf(MSG_DEBUG, | |
1539 | "DPP: Peer protocol key curve (%s) does not match the required netAccessKey curve (%s) - %s", | |
1540 | auth->curve->name, | |
1541 | auth->conf->net_access_key_curve->name, | |
1542 | auth->waiting_new_key ? | |
1543 | "the required key not received" : | |
1544 | "request a new key"); | |
1545 | if (auth->waiting_new_key) | |
1546 | auth->waiting_new_key = false; /* failed */ | |
1547 | else | |
1548 | auth->waiting_new_key = true; | |
1549 | goto fail; | |
1550 | } | |
1551 | #endif /* CONFIG_DPP3 */ | |
1552 | if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, | |
1553 | nak_curve) < 0) { | |
1487 | 1554 | wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); |
1488 | 1555 | goto fail; |
1489 | 1556 | } |
1595 | 1662 | wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object", |
1596 | 1663 | wpabuf_head(buf), wpabuf_len(buf)); |
1597 | 1664 | |
1665 | #ifdef CONFIG_DPP3 | |
1666 | if (!auth->conf->net_access_key_curve) { | |
1667 | /* All netAccessKey values used in the network will have to be | |
1668 | * from the same curve for network introduction to work, so | |
1669 | * hardcode the first used netAccessKey curve for consecutive | |
1670 | * operations if there was no explicit configuration of which | |
1671 | * curve to use. */ | |
1672 | wpa_printf(MSG_DEBUG, | |
1673 | "DPP: Update Configurator to require netAccessKey curve %s based on first provisioning", | |
1674 | nak_curve->name); | |
1675 | auth->conf->net_access_key_curve = nak_curve; | |
1676 | } | |
1677 | #endif /* CONFIG_DPP3 */ | |
1678 | ||
1598 | 1679 | out: |
1599 | 1680 | os_free(signed_conn); |
1600 | 1681 | wpabuf_free(dppcon); |
1636 | 1717 | } |
1637 | 1718 | |
1638 | 1719 | |
1720 | static int dpp_get_peer_bi_id(struct dpp_authentication *auth) | |
1721 | { | |
1722 | struct dpp_bootstrap_info *bi; | |
1723 | ||
1724 | if (auth->peer_bi) | |
1725 | return auth->peer_bi->id; | |
1726 | if (auth->tmp_peer_bi) | |
1727 | return auth->tmp_peer_bi->id; | |
1728 | ||
1729 | bi = os_zalloc(sizeof(*bi)); | |
1730 | if (!bi) | |
1731 | return -1; | |
1732 | bi->id = dpp_next_id(auth->global); | |
1733 | dl_list_add(&auth->global->bootstrap, &bi->list); | |
1734 | auth->tmp_peer_bi = bi; | |
1735 | return bi->id; | |
1736 | } | |
1737 | ||
1738 | ||
1639 | 1739 | static struct wpabuf * |
1640 | 1740 | dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, |
1641 | 1741 | int idx, bool cert_req) |
1664 | 1764 | conf = auth->conf2_ap; |
1665 | 1765 | } |
1666 | 1766 | if (!conf) { |
1667 | if (idx == 0) | |
1767 | if (idx == 0) { | |
1768 | if (auth->use_config_query) { | |
1769 | wpa_printf(MSG_DEBUG, | |
1770 | "DPP: No configuration available for Enrollee(%s) - waiting for configuration", | |
1771 | dpp_netrole_str(netrole)); | |
1772 | auth->waiting_config = true; | |
1773 | dpp_get_peer_bi_id(auth); | |
1774 | return NULL; | |
1775 | } | |
1668 | 1776 | wpa_printf(MSG_DEBUG, |
1669 | 1777 | "DPP: No configuration available for Enrollee(%s) - reject configuration request", |
1670 | 1778 | dpp_netrole_str(netrole)); |
1779 | } | |
1671 | 1780 | return NULL; |
1672 | 1781 | } |
1673 | 1782 | |
1694 | 1803 | dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, |
1695 | 1804 | u16 e_nonce_len, enum dpp_netrole netrole, bool cert_req) |
1696 | 1805 | { |
1697 | struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL; | |
1806 | struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL, *pc = NULL; | |
1698 | 1807 | size_t clear_len, attr_len; |
1699 | 1808 | struct wpabuf *clear = NULL, *msg = NULL; |
1700 | 1809 | u8 *wrapped; |
1721 | 1830 | } |
1722 | 1831 | } |
1723 | 1832 | |
1833 | if (!conf && auth->waiting_config) | |
1834 | return NULL; | |
1724 | 1835 | if (conf || env_data) |
1725 | 1836 | status = DPP_STATUS_OK; |
1726 | 1837 | else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta && |
1727 | 1838 | auth->conf_sta->akm == DPP_AKM_DOT1X && !auth->waiting_csr) |
1728 | 1839 | status = DPP_STATUS_CSR_NEEDED; |
1840 | #ifdef CONFIG_DPP3 | |
1841 | else if (auth->waiting_new_key) | |
1842 | status = DPP_STATUS_NEW_KEY_NEEDED; | |
1843 | #endif /* CONFIG_DPP3 */ | |
1729 | 1844 | else |
1730 | 1845 | status = DPP_STATUS_CONFIGURE_FAILURE; |
1731 | 1846 | forced_status: |
1745 | 1860 | if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta && |
1746 | 1861 | auth->conf_sta->csrattrs) |
1747 | 1862 | clear_len += 4 + os_strlen(auth->conf_sta->csrattrs); |
1863 | #ifdef CONFIG_DPP3 | |
1864 | if (status == DPP_STATUS_NEW_KEY_NEEDED) { | |
1865 | struct crypto_ec_key *new_pc; | |
1866 | ||
1867 | clear_len += 6; /* Finite Cyclic Group attribute */ | |
1868 | ||
1869 | wpa_printf(MSG_DEBUG, | |
1870 | "DPP: Generate a new own protocol key for the curve %s", | |
1871 | auth->conf->net_access_key_curve->name); | |
1872 | new_pc = dpp_gen_keypair(auth->conf->net_access_key_curve); | |
1873 | if (!new_pc) { | |
1874 | wpa_printf(MSG_DEBUG, "DPP: Failed to generate new Pc"); | |
1875 | return NULL; | |
1876 | } | |
1877 | pc = crypto_ec_key_get_pubkey_point(new_pc, 0); | |
1878 | if (!pc) { | |
1879 | crypto_ec_key_deinit(new_pc); | |
1880 | return NULL; | |
1881 | } | |
1882 | crypto_ec_key_deinit(auth->own_protocol_key); | |
1883 | auth->own_protocol_key = new_pc; | |
1884 | auth->new_curve = auth->conf->net_access_key_curve; | |
1885 | clear_len += 4 + wpabuf_len(pc); | |
1886 | } | |
1887 | #endif /* CONFIG_DPP3 */ | |
1748 | 1888 | clear = wpabuf_alloc(clear_len); |
1749 | 1889 | attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE; |
1750 | 1890 | #ifdef CONFIG_TESTING_OPTIONS |
1822 | 1962 | wpabuf_put_str(clear, auth->conf_sta->csrattrs); |
1823 | 1963 | } |
1824 | 1964 | |
1965 | #ifdef CONFIG_DPP3 | |
1966 | if (status == DPP_STATUS_NEW_KEY_NEEDED && auth->conf && | |
1967 | auth->conf->net_access_key_curve) { | |
1968 | u16 ike_group = auth->conf->net_access_key_curve->ike_group; | |
1969 | ||
1970 | /* Finite Cyclic Group attribute */ | |
1971 | wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u", | |
1972 | ike_group); | |
1973 | wpabuf_put_le16(clear, DPP_ATTR_FINITE_CYCLIC_GROUP); | |
1974 | wpabuf_put_le16(clear, 2); | |
1975 | wpabuf_put_le16(clear, ike_group); | |
1976 | ||
1977 | if (pc) { | |
1978 | wpa_printf(MSG_DEBUG, "DPP: Pc"); | |
1979 | wpabuf_put_le16(clear, DPP_ATTR_R_PROTOCOL_KEY); | |
1980 | wpabuf_put_le16(clear, wpabuf_len(pc)); | |
1981 | wpabuf_put_buf(clear, pc); | |
1982 | } | |
1983 | } | |
1984 | #endif /* CONFIG_DPP3 */ | |
1985 | ||
1825 | 1986 | #ifdef CONFIG_TESTING_OPTIONS |
1826 | 1987 | skip_config_obj: |
1827 | 1988 | if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) { |
1872 | 2033 | wpabuf_clear_free(conf2); |
1873 | 2034 | wpabuf_clear_free(env_data); |
1874 | 2035 | wpabuf_clear_free(clear); |
2036 | wpabuf_free(pc); | |
1875 | 2037 | |
1876 | 2038 | return msg; |
1877 | 2039 | fail: |
1893 | 2055 | struct json_token *root = NULL, *token; |
1894 | 2056 | enum dpp_netrole netrole; |
1895 | 2057 | struct wpabuf *cert_req = NULL; |
2058 | #ifdef CONFIG_DPP3 | |
2059 | const u8 *i_proto; | |
2060 | u16 i_proto_len; | |
2061 | #endif /* CONFIG_DPP3 */ | |
1896 | 2062 | |
1897 | 2063 | #ifdef CONFIG_TESTING_OPTIONS |
1898 | 2064 | if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) { |
1946 | 2112 | wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len); |
1947 | 2113 | os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); |
1948 | 2114 | |
2115 | #ifdef CONFIG_DPP3 | |
2116 | i_proto = dpp_get_attr(unwrapped, unwrapped_len, | |
2117 | DPP_ATTR_I_PROTOCOL_KEY, &i_proto_len); | |
2118 | if (i_proto && !auth->waiting_new_key) { | |
2119 | dpp_auth_fail(auth, | |
2120 | "Enrollee included a new protocol key even though one was not expected"); | |
2121 | goto fail; | |
2122 | } | |
2123 | if (i_proto) { | |
2124 | struct crypto_ec_key *pe; | |
2125 | u8 auth_i[DPP_MAX_HASH_LEN]; | |
2126 | const u8 *rx_auth_i; | |
2127 | u16 rx_auth_i_len; | |
2128 | ||
2129 | wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key (new Pe)", | |
2130 | i_proto, i_proto_len); | |
2131 | ||
2132 | pe = dpp_set_pubkey_point(auth->own_protocol_key, | |
2133 | i_proto, i_proto_len); | |
2134 | if (!pe) { | |
2135 | dpp_auth_fail(auth, | |
2136 | "Invalid Initiator Protocol Key (Pe)"); | |
2137 | goto fail; | |
2138 | } | |
2139 | dpp_debug_print_key("New Peer Protocol Key (Pe)", pe); | |
2140 | crypto_ec_key_deinit(auth->peer_protocol_key); | |
2141 | auth->peer_protocol_key = pe; | |
2142 | auth->new_key_received = true; | |
2143 | auth->waiting_new_key = false; | |
2144 | ||
2145 | if (dpp_derive_auth_i(auth, auth_i) < 0) | |
2146 | goto fail; | |
2147 | ||
2148 | rx_auth_i = dpp_get_attr(unwrapped, unwrapped_len, | |
2149 | DPP_ATTR_I_AUTH_TAG, &rx_auth_i_len); | |
2150 | if (!rx_auth_i) { | |
2151 | dpp_auth_fail(auth, | |
2152 | "Missing Initiator Authentication Tag"); | |
2153 | goto fail; | |
2154 | } | |
2155 | if (rx_auth_i_len != auth->curve->hash_len || | |
2156 | os_memcmp(rx_auth_i, auth_i, auth->curve->hash_len) != 0) { | |
2157 | dpp_auth_fail(auth, | |
2158 | "Mismatch in Initiator Authenticating Tag"); | |
2159 | wpa_hexdump(MSG_DEBUG, "DPP: Received Auth-I", | |
2160 | rx_auth_i, rx_auth_i_len); | |
2161 | wpa_hexdump(MSG_DEBUG, "DPP: Derived Auth-I'", | |
2162 | auth_i, auth->curve->hash_len); | |
2163 | goto fail; | |
2164 | } | |
2165 | } | |
2166 | #endif /* CONFIG_DPP3 */ | |
2167 | ||
1949 | 2168 | config_attr = dpp_get_attr(unwrapped, unwrapped_len, |
1950 | 2169 | DPP_ATTR_CONFIG_ATTR_OBJ, |
1951 | 2170 | &config_attr_len); |
1969 | 2188 | goto fail; |
1970 | 2189 | } |
1971 | 2190 | wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string); |
2191 | os_free(auth->e_name); | |
2192 | auth->e_name = os_strdup(token->string); | |
1972 | 2193 | |
1973 | 2194 | token = json_get_member(root, "wi-fi_tech"); |
1974 | 2195 | if (!token || token->type != JSON_STRING) { |
2008 | 2229 | wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string); |
2009 | 2230 | wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s", |
2010 | 2231 | token->string); |
2232 | os_free(auth->e_mud_url); | |
2233 | auth->e_mud_url = os_strdup(token->string); | |
2011 | 2234 | } |
2012 | 2235 | |
2013 | 2236 | token = json_get_member(root, "bandSupport"); |
2043 | 2266 | } |
2044 | 2267 | pos += res; |
2045 | 2268 | } |
2046 | os_free(opclass); | |
2269 | os_free(auth->e_band_support); | |
2270 | auth->e_band_support = opclass; | |
2047 | 2271 | wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s", |
2048 | 2272 | txt); |
2049 | 2273 | } |
2061 | 2285 | goto cont; |
2062 | 2286 | } |
2063 | 2287 | |
2064 | if (auth->peer_bi) { | |
2065 | id = auth->peer_bi->id; | |
2066 | } else if (auth->tmp_peer_bi) { | |
2067 | id = auth->tmp_peer_bi->id; | |
2068 | } else { | |
2069 | struct dpp_bootstrap_info *bi; | |
2070 | ||
2071 | bi = os_zalloc(sizeof(*bi)); | |
2072 | if (!bi) | |
2073 | goto fail; | |
2074 | bi->id = dpp_next_id(auth->global); | |
2075 | dl_list_add(&auth->global->bootstrap, &bi->list); | |
2076 | auth->tmp_peer_bi = bi; | |
2077 | id = bi->id; | |
2078 | } | |
2288 | id = dpp_get_peer_bi_id(auth); | |
2289 | if (id < 0) | |
2290 | goto fail; | |
2079 | 2291 | |
2080 | 2292 | wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA"); |
2081 | 2293 | txt = base64_encode_no_lf(wpabuf_head(cert_req), |
2951 | 3163 | goto fail; |
2952 | 3164 | } |
2953 | 3165 | #endif /* CONFIG_DPP2 */ |
3166 | #ifdef CONFIG_DPP3 | |
3167 | if (status[0] == DPP_STATUS_NEW_KEY_NEEDED) { | |
3168 | const u8 *fcgroup, *r_proto; | |
3169 | u16 fcgroup_len, r_proto_len; | |
3170 | u16 group; | |
3171 | const struct dpp_curve_params *curve; | |
3172 | struct crypto_ec_key *new_pe; | |
3173 | struct crypto_ec_key *pc; | |
3174 | ||
3175 | fcgroup = dpp_get_attr(unwrapped, unwrapped_len, | |
3176 | DPP_ATTR_FINITE_CYCLIC_GROUP, | |
3177 | &fcgroup_len); | |
3178 | if (!fcgroup || fcgroup_len != 2) { | |
3179 | dpp_auth_fail(auth, | |
3180 | "Missing or invalid required Finite Cyclic Group attribute"); | |
3181 | goto fail; | |
3182 | } | |
3183 | group = WPA_GET_LE16(fcgroup); | |
3184 | ||
3185 | wpa_printf(MSG_DEBUG, | |
3186 | "DPP: Configurator requested a new protocol key from group %u", | |
3187 | group); | |
3188 | curve = dpp_get_curve_ike_group(group); | |
3189 | if (!curve) { | |
3190 | dpp_auth_fail(auth, | |
3191 | "Unsupported group for new protocol key"); | |
3192 | goto fail; | |
3193 | } | |
3194 | ||
3195 | new_pe = dpp_gen_keypair(curve); | |
3196 | if (!new_pe) { | |
3197 | dpp_auth_fail(auth, | |
3198 | "Failed to generate a new protocol key"); | |
3199 | goto fail; | |
3200 | } | |
3201 | ||
3202 | crypto_ec_key_deinit(auth->own_protocol_key); | |
3203 | auth->own_protocol_key = new_pe; | |
3204 | auth->new_curve = curve; | |
3205 | ||
3206 | r_proto = dpp_get_attr(unwrapped, unwrapped_len, | |
3207 | DPP_ATTR_R_PROTOCOL_KEY, | |
3208 | &r_proto_len); | |
3209 | if (!r_proto) { | |
3210 | dpp_auth_fail(auth, | |
3211 | "Missing required Responder Protocol Key attribute (Pc)"); | |
3212 | goto fail; | |
3213 | } | |
3214 | wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key (new Pc)", | |
3215 | r_proto, r_proto_len); | |
3216 | ||
3217 | pc = dpp_set_pubkey_point(new_pe, r_proto, r_proto_len); | |
3218 | if (!pc) { | |
3219 | dpp_auth_fail(auth, "Invalid Responder Protocol Key (Pc)"); | |
3220 | goto fail; | |
3221 | } | |
3222 | dpp_debug_print_key("New Peer Protocol Key (Pc)", pc); | |
3223 | ||
3224 | crypto_ec_key_deinit(auth->peer_protocol_key); | |
3225 | auth->peer_protocol_key = pc; | |
3226 | ||
3227 | auth->waiting_new_key = true; | |
3228 | ret = -3; | |
3229 | goto fail; | |
3230 | } | |
3231 | #endif /* CONFIG_DPP3 */ | |
2954 | 3232 | if (status[0] != DPP_STATUS_OK) { |
2955 | 3233 | dpp_auth_fail(auth, "Configurator rejected configuration"); |
2956 | 3234 | goto fail; |
4172 | 4450 | |
4173 | 4451 | int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) |
4174 | 4452 | { |
4175 | char *curve = NULL; | |
4453 | char *curve; | |
4176 | 4454 | char *key = NULL, *ppkey = NULL; |
4177 | 4455 | u8 *privkey = NULL, *pp_key = NULL; |
4178 | 4456 | size_t privkey_len = 0, pp_key_len = 0; |
4179 | 4457 | int ret = -1; |
4180 | 4458 | struct dpp_configurator *conf = NULL; |
4459 | const struct dpp_curve_params *net_access_key_curve = NULL; | |
4460 | ||
4461 | curve = get_param(cmd, " net_access_key_curve="); | |
4462 | if (curve) { | |
4463 | net_access_key_curve = dpp_get_curve_name(curve); | |
4464 | if (!net_access_key_curve) { | |
4465 | wpa_printf(MSG_DEBUG, | |
4466 | "DPP: Unsupported net_access_key_curve: %s", | |
4467 | curve); | |
4468 | goto fail; | |
4469 | } | |
4470 | os_free(curve); | |
4471 | } | |
4181 | 4472 | |
4182 | 4473 | curve = get_param(cmd, " curve="); |
4183 | 4474 | key = get_param(cmd, " key="); |
4204 | 4495 | if (!conf) |
4205 | 4496 | goto fail; |
4206 | 4497 | |
4498 | conf->net_access_key_curve = net_access_key_curve; | |
4207 | 4499 | conf->id = dpp_next_configurator_id(dpp); |
4208 | 4500 | dl_list_add(&dpp->configurator, &conf->list); |
4209 | 4501 | ret = conf->id; |
4219 | 4511 | } |
4220 | 4512 | |
4221 | 4513 | |
4514 | int dpp_configurator_set(struct dpp_global *dpp, const char *cmd) | |
4515 | { | |
4516 | unsigned int id; | |
4517 | struct dpp_configurator *conf; | |
4518 | char *curve; | |
4519 | ||
4520 | id = atoi(cmd); | |
4521 | conf = dpp_configurator_get_id(dpp, id); | |
4522 | if (!conf) | |
4523 | return -1; | |
4524 | ||
4525 | curve = get_param(cmd, " net_access_key_curve="); | |
4526 | if (curve) { | |
4527 | const struct dpp_curve_params *net_access_key_curve; | |
4528 | ||
4529 | net_access_key_curve = dpp_get_curve_name(curve); | |
4530 | os_free(curve); | |
4531 | if (!net_access_key_curve) | |
4532 | return -1; | |
4533 | conf->net_access_key_curve = net_access_key_curve; | |
4534 | } | |
4535 | ||
4536 | return 0; | |
4537 | } | |
4538 | ||
4539 | ||
4222 | 4540 | static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id) |
4223 | 4541 | { |
4224 | 4542 | struct dpp_configurator *conf, *tmp; |
1 | 1 | * DPP functionality shared between hostapd and wpa_supplicant |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2018-2020, The Linux Foundation |
4 | * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
108 | 109 | DPP_STATUS_CONFIGURE_PENDING = 11, |
109 | 110 | DPP_STATUS_CSR_NEEDED = 12, |
110 | 111 | DPP_STATUS_CSR_BAD = 13, |
112 | DPP_STATUS_NEW_KEY_NEEDED = 14, | |
111 | 113 | }; |
112 | 114 | |
113 | 115 | /* DPP Reconfig Flags object - connectorKey values */ |
170 | 172 | |
171 | 173 | #define PKEX_COUNTER_T_LIMIT 5 |
172 | 174 | |
175 | enum dpp_pkex_ver { | |
176 | PKEX_VER_AUTO, | |
177 | PKEX_VER_ONLY_1, | |
178 | PKEX_VER_ONLY_2, | |
179 | }; | |
180 | ||
173 | 181 | struct dpp_pkex { |
174 | 182 | void *msg_ctx; |
175 | 183 | unsigned int initiator:1; |
176 | 184 | unsigned int exchange_done:1; |
177 | 185 | unsigned int failed:1; |
178 | 186 | unsigned int v2:1; |
187 | unsigned int forced_ver:1; | |
179 | 188 | struct dpp_bootstrap_info *own_bi; |
180 | 189 | u8 own_mac[ETH_ALEN]; |
181 | 190 | u8 peer_mac[ETH_ALEN]; |
249 | 258 | void *msg_ctx; |
250 | 259 | u8 peer_version; |
251 | 260 | const struct dpp_curve_params *curve; |
261 | const struct dpp_curve_params *new_curve; | |
252 | 262 | struct dpp_bootstrap_info *peer_bi; |
253 | 263 | struct dpp_bootstrap_info *own_bi; |
254 | 264 | struct dpp_bootstrap_info *tmp_own_bi; |
349 | 359 | char *trusted_eap_server_name; |
350 | 360 | struct wpabuf *cacert; |
351 | 361 | struct wpabuf *certbag; |
352 | void *cert_resp_ctx; | |
362 | bool waiting_new_key; | |
363 | bool new_key_received; | |
364 | void *config_resp_ctx; | |
353 | 365 | void *gas_server_ctx; |
366 | bool use_config_query; | |
367 | bool waiting_config; | |
368 | char *e_name; | |
369 | char *e_mud_url; | |
370 | int *e_band_support; | |
354 | 371 | #ifdef CONFIG_TESTING_OPTIONS |
355 | 372 | char *config_obj_override; |
356 | 373 | char *discovery_override; |
367 | 384 | u8 kid_hash[SHA256_MAC_LEN]; |
368 | 385 | char *kid; |
369 | 386 | const struct dpp_curve_params *curve; |
387 | const struct dpp_curve_params *net_access_key_curve; | |
370 | 388 | char *connector; /* own Connector for reconfiguration */ |
371 | 389 | struct crypto_ec_key *connector_key; |
372 | 390 | struct crypto_ec_key *pp_key; |
400 | 418 | void *msg_ctx; |
401 | 419 | void *cb_ctx; |
402 | 420 | int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); |
421 | bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); | |
403 | 422 | }; |
404 | 423 | |
405 | 424 | #ifdef CONFIG_TESTING_OPTIONS |
498 | 517 | DPP_TEST_REJECT_CONFIG = 91, |
499 | 518 | DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ = 92, |
500 | 519 | DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_RESP = 93, |
520 | DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ = 94, | |
521 | DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_RESP = 95, | |
522 | DPP_TEST_INVALID_PROTOCOL_VERSION_RECONFIG_AUTH_REQ = 96, | |
523 | DPP_TEST_NO_PROTOCOL_VERSION_RECONFIG_AUTH_REQ = 97, | |
501 | 524 | }; |
502 | 525 | |
503 | 526 | extern enum dpp_test_behavior dpp_test; |
519 | 542 | int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info); |
520 | 543 | int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi, |
521 | 544 | struct dpp_bootstrap_info *peer_bi); |
545 | const char * dpp_netrole_str(enum dpp_netrole netrole); | |
522 | 546 | struct dpp_authentication * |
523 | 547 | dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx); |
524 | 548 | struct hostapd_hw_modes; |
548 | 572 | const u8 *attr_start, size_t attr_len); |
549 | 573 | int dpp_notify_new_qr_code(struct dpp_authentication *auth, |
550 | 574 | struct dpp_bootstrap_info *peer_bi); |
575 | void dpp_controller_pkex_add(struct dpp_global *dpp, | |
576 | struct dpp_bootstrap_info *bi, | |
577 | const char *code, const char *identifier); | |
551 | 578 | struct dpp_configuration * dpp_configuration_alloc(const char *type); |
552 | 579 | int dpp_akm_psk(enum dpp_akm akm); |
553 | 580 | int dpp_akm_sae(enum dpp_akm akm); |
663 | 690 | struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, |
664 | 691 | const u8 *hash); |
665 | 692 | int dpp_configurator_add(struct dpp_global *dpp, const char *cmd); |
693 | int dpp_configurator_set(struct dpp_global *dpp, const char *cmd); | |
666 | 694 | int dpp_configurator_remove(struct dpp_global *dpp, const char *id); |
667 | 695 | int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, |
668 | 696 | char *buf, size_t buflen); |
680 | 708 | size_t data_len); |
681 | 709 | int dpp_controller_start(struct dpp_global *dpp, |
682 | 710 | struct dpp_controller_config *config); |
711 | int dpp_controller_set_params(struct dpp_global *dpp, | |
712 | const char *configurator_params); | |
683 | 713 | void dpp_controller_stop(struct dpp_global *dpp); |
684 | 714 | void dpp_controller_stop_for_ctx(struct dpp_global *dpp, void *cb_ctx); |
685 | 715 | struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, |
686 | 716 | unsigned int id); |
687 | 717 | void dpp_controller_new_qr_code(struct dpp_global *dpp, |
688 | 718 | struct dpp_bootstrap_info *bi); |
719 | int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex, | |
720 | const struct hostapd_ip_addr *addr, int port, | |
721 | void *msg_ctx, void *cb_ctx, | |
722 | int (*pkex_done)(void *ctx, void *conn, | |
723 | struct dpp_bootstrap_info *bi)); | |
689 | 724 | int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, |
690 | 725 | const struct hostapd_ip_addr *addr, int port, |
691 | 726 | const char *name, enum dpp_netrole netrole, void *msg_ctx, |
692 | 727 | void *cb_ctx, |
693 | 728 | int (*process_conf_obj)(void *ctx, |
694 | struct dpp_authentication *auth)); | |
729 | struct dpp_authentication *auth), | |
730 | bool (*tcp_msg_sent)(void *ctx, | |
731 | struct dpp_authentication *auth)); | |
732 | int dpp_tcp_auth(struct dpp_global *dpp, void *_conn, | |
733 | struct dpp_authentication *auth, const char *name, | |
734 | enum dpp_netrole netrole, | |
735 | int (*process_conf_obj)(void *ctx, | |
736 | struct dpp_authentication *auth), | |
737 | bool (*tcp_msg_sent)(void *ctx, | |
738 | struct dpp_authentication *auth)); | |
739 | bool dpp_tcp_conn_status_requested(struct dpp_global *dpp); | |
740 | void dpp_tcp_send_conn_status(struct dpp_global *dpp, | |
741 | enum dpp_status_error result, | |
742 | const u8 *ssid, size_t ssid_len, | |
743 | const char *channel_list); | |
695 | 744 | |
696 | 745 | struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); |
697 | 746 | void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src, |
2058 | 2058 | struct wpabuf *priv_key; |
2059 | 2059 | u8 cp[DPP_CP_LEN]; |
2060 | 2060 | char *password = NULL; |
2061 | size_t password_len; | |
2061 | size_t password_len = 0; | |
2062 | 2062 | int hash_sign_algo; |
2063 | 2063 | |
2064 | 2064 | /* TODO: use auth->csrattrs */ |
2354 | 2354 | #endif /* CONFIG_DPP2 */ |
2355 | 2355 | |
2356 | 2356 | |
2357 | #ifdef CONFIG_DPP3 | |
2358 | int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i) | |
2359 | { | |
2360 | int ret = -1, res; | |
2361 | u8 Sx[DPP_MAX_SHARED_SECRET_LEN]; | |
2362 | size_t Sx_len; | |
2363 | unsigned int hash_len; | |
2364 | const char *info = "New DPP Protocol Key"; | |
2365 | const u8 *addr[3]; | |
2366 | size_t len[3]; | |
2367 | u8 tmp[DPP_MAX_HASH_LEN], k[DPP_MAX_HASH_LEN]; | |
2368 | struct wpabuf *pcx = NULL, *pex = NULL; | |
2369 | ||
2370 | hash_len = auth->curve->hash_len; | |
2371 | ||
2372 | /* | |
2373 | * Configurator: S = pc * Pe | |
2374 | * Enrollee: S = pe * Pc | |
2375 | * k = HKDF(bk, "New DPP Protocol Key", S.x) | |
2376 | * = HKDF-Expand(HKDF-Extract(bk, S.X), "New DPP Protocol Key", | |
2377 | * len(new-curve-hash-out)) | |
2378 | * Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x) | |
2379 | * | |
2380 | * auth->own_protocol_key and auth->peer_protocol_key have already been | |
2381 | * updated to use the new keys. The new curve determines the size of | |
2382 | * the (new) protocol keys and S.x. The other parameters (bk, hash | |
2383 | * algorithm, k) are determined based on the initially determined curve | |
2384 | * during the (re)authentication exchange. | |
2385 | */ | |
2386 | ||
2387 | if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key, | |
2388 | Sx, &Sx_len) < 0) | |
2389 | goto fail; | |
2390 | ||
2391 | wpa_hexdump_key(MSG_DEBUG, "DPP: S.x", Sx, Sx_len); | |
2392 | ||
2393 | /* tmp = HKDF-Extract(bk, S.x) */ | |
2394 | addr[0] = Sx; | |
2395 | len[0] = Sx_len; | |
2396 | res = dpp_hmac_vector(hash_len, auth->bk, hash_len, 1, addr, len, tmp); | |
2397 | if (res < 0) | |
2398 | goto fail; | |
2399 | wpa_hexdump_key(MSG_DEBUG, "DPP: HKDF-Extract(bk, S.x)", | |
2400 | tmp, hash_len); | |
2401 | /* k = HKDF-Expand(tmp, "New DPP Protocol Key", len(hash-output)) | |
2402 | */ | |
2403 | res = dpp_hkdf_expand(hash_len, tmp, hash_len, info, k, hash_len); | |
2404 | if (res < 0) | |
2405 | return -1; | |
2406 | ||
2407 | wpa_hexdump_key(MSG_DEBUG, | |
2408 | "DPP: k = HKDF-Expand(\"New DPP Protocol Key\")", | |
2409 | k, hash_len); | |
2410 | ||
2411 | /* Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x) */ | |
2412 | addr[0] = auth->e_nonce; | |
2413 | len[0] = auth->curve->nonce_len; | |
2414 | ||
2415 | if (auth->configurator) { | |
2416 | pcx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); | |
2417 | pex = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, | |
2418 | 0); | |
2419 | } else { | |
2420 | pcx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, | |
2421 | 0); | |
2422 | pex = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); | |
2423 | } | |
2424 | if (!pcx || !pex) | |
2425 | goto fail; | |
2426 | addr[1] = wpabuf_head(pcx); | |
2427 | len[1] = wpabuf_len(pcx) / 2; | |
2428 | addr[2] = wpabuf_head(pex); | |
2429 | len[2] = wpabuf_len(pex) / 2; | |
2430 | ||
2431 | if (dpp_hmac_vector(hash_len, k, hash_len, 3, addr, len, auth_i) < 0) | |
2432 | goto fail; | |
2433 | wpa_hexdump_key(MSG_DEBUG, | |
2434 | "DPP: Auth-I = HMAC(k, E-nonce | Pc.x | Pe.x)", | |
2435 | auth_i, hash_len); | |
2436 | ret = 0; | |
2437 | fail: | |
2438 | forced_memzero(Sx, sizeof(Sx)); | |
2439 | forced_memzero(tmp, sizeof(tmp)); | |
2440 | forced_memzero(k, sizeof(k)); | |
2441 | wpabuf_free(pcx); | |
2442 | wpabuf_free(pex); | |
2443 | return ret; | |
2444 | } | |
2445 | #endif /* CONFIG_DPP3 */ | |
2446 | ||
2447 | ||
2357 | 2448 | #ifdef CONFIG_TESTING_OPTIONS |
2358 | 2449 | |
2359 | 2450 | int dpp_test_gen_invalid_key(struct wpabuf *msg, |
1 | 1 | * DPP module internal definitions |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2018-2020, The Linux Foundation |
4 | * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
21 | 22 | struct dl_list tcp_init; /* struct dpp_connection */ |
22 | 23 | void *cb_ctx; |
23 | 24 | int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); |
25 | bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); | |
24 | 26 | void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); |
25 | 27 | #endif /* CONFIG_DPP2 */ |
26 | 28 | }; |
133 | 135 | struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey, |
134 | 136 | struct crypto_ec_key *a_nonce, |
135 | 137 | struct crypto_ec_key *e_prime_id); |
138 | int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i); | |
136 | 139 | char * dpp_sign_connector(struct dpp_configurator *conf, |
137 | 140 | const struct wpabuf *dppcon); |
138 | 141 | int dpp_test_gen_invalid_key(struct wpabuf *msg, |
468 | 468 | pkex->t = bi->pkex_t; |
469 | 469 | pkex->msg_ctx = msg_ctx; |
470 | 470 | pkex->own_bi = bi; |
471 | os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); | |
472 | os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); | |
471 | if (own_mac) | |
472 | os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); | |
473 | if (peer_mac) | |
474 | os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); | |
473 | 475 | if (identifier) { |
474 | 476 | pkex->identifier = os_strdup(identifier); |
475 | 477 | if (!pkex->identifier) |
741 | 743 | } |
742 | 744 | #endif /* CONFIG_DPP2 */ |
743 | 745 | |
744 | os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); | |
746 | if (peer_mac) | |
747 | os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); | |
745 | 748 | |
746 | 749 | attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS, |
747 | 750 | &attr_status_len); |
1340 | 1343 | return NULL; |
1341 | 1344 | bi->id = dpp_next_id(dpp); |
1342 | 1345 | bi->type = DPP_BOOTSTRAP_PKEX; |
1343 | os_memcpy(bi->mac_addr, peer, ETH_ALEN); | |
1344 | bi->num_freq = 1; | |
1345 | bi->freq[0] = freq; | |
1346 | if (peer) | |
1347 | os_memcpy(bi->mac_addr, peer, ETH_ALEN); | |
1348 | if (freq) { | |
1349 | bi->num_freq = 1; | |
1350 | bi->freq[0] = freq; | |
1351 | } | |
1346 | 1352 | bi->curve = pkex->own_bi->curve; |
1347 | 1353 | bi->pubkey = pkex->peer_bootstrap_key; |
1348 | 1354 | pkex->peer_bootstrap_key = NULL; |
130 | 130 | { |
131 | 131 | struct wpabuf *msg; |
132 | 132 | size_t attr_len; |
133 | u8 ver = DPP_VERSION; | |
133 | 134 | |
134 | 135 | /* Build DPP Reconfig Authentication Request frame attributes */ |
135 | 136 | attr_len = 4 + 1 + 4 + 1 + 4 + os_strlen(auth->conf->connector) + |
143 | 144 | wpabuf_put_le16(msg, 1); |
144 | 145 | wpabuf_put_u8(msg, auth->transaction_id); |
145 | 146 | |
147 | #ifdef CONFIG_TESTING_OPTIONS | |
148 | if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_RECONFIG_AUTH_REQ) { | |
149 | wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version"); | |
150 | goto skip_proto_ver; | |
151 | } | |
152 | if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_RECONFIG_AUTH_REQ) { | |
153 | wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version"); | |
154 | ver = 1; | |
155 | } | |
156 | #endif /* CONFIG_TESTING_OPTIONS */ | |
157 | ||
146 | 158 | /* Protocol Version */ |
147 | 159 | wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); |
148 | 160 | wpabuf_put_le16(msg, 1); |
149 | wpabuf_put_u8(msg, DPP_VERSION); | |
161 | wpabuf_put_u8(msg, ver); | |
162 | ||
163 | #ifdef CONFIG_TESTING_OPTIONS | |
164 | skip_proto_ver: | |
165 | #endif /* CONFIG_TESTING_OPTIONS */ | |
150 | 166 | |
151 | 167 | /* DPP Connector */ |
152 | 168 | wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); |
0 | 0 | /* |
1 | 1 | * DPP over TCP |
2 | 2 | * Copyright (c) 2019-2020, The Linux Foundation |
3 | * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. | |
3 | 4 | * |
4 | 5 | * This software may be distributed under the terms of the BSD license. |
5 | 6 | * See README for more details. |
23 | 24 | struct dpp_controller *ctrl; |
24 | 25 | struct dpp_relay_controller *relay; |
25 | 26 | struct dpp_global *global; |
27 | struct dpp_pkex *pkex; | |
26 | 28 | struct dpp_authentication *auth; |
27 | 29 | void *msg_ctx; |
28 | 30 | void *cb_ctx; |
29 | 31 | int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); |
32 | int (*pkex_done)(void *ctx, void *conn, struct dpp_bootstrap_info *bi); | |
33 | bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); | |
30 | 34 | int sock; |
31 | 35 | u8 mac_addr[ETH_ALEN]; |
32 | 36 | unsigned int freq; |
70 | 74 | struct dl_list conn; /* struct dpp_connection */ |
71 | 75 | char *configurator_params; |
72 | 76 | enum dpp_netrole netrole; |
77 | struct dpp_bootstrap_info *pkex_bi; | |
78 | char *pkex_code; | |
79 | char *pkex_identifier; | |
73 | 80 | void *msg_ctx; |
74 | 81 | void *cb_ctx; |
75 | 82 | int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); |
83 | bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); | |
76 | 84 | }; |
77 | 85 | |
78 | 86 | static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); |
80 | 88 | static void dpp_controller_auth_success(struct dpp_connection *conn, |
81 | 89 | int initiator); |
82 | 90 | static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx); |
91 | #ifdef CONFIG_DPP3 | |
92 | static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx); | |
93 | #endif /* CONFIG_DPP3 */ | |
83 | 94 | static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx); |
84 | 95 | static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx); |
85 | 96 | |
98 | 109 | eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL); |
99 | 110 | eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL); |
100 | 111 | eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL); |
112 | #ifdef CONFIG_DPP3 | |
113 | eloop_cancel_timeout(dpp_tcp_build_new_key, conn, NULL); | |
114 | #endif /* CONFIG_DPP3 */ | |
101 | 115 | wpabuf_free(conn->msg); |
102 | 116 | wpabuf_free(conn->msg_out); |
103 | 117 | dpp_auth_deinit(conn->auth); |
118 | dpp_pkex_free(conn->pkex); | |
104 | 119 | os_free(conn->name); |
105 | 120 | os_free(conn); |
106 | 121 | } |
182 | 197 | conn->on_tcp_tx_complete_gas_done = 0; |
183 | 198 | return; |
184 | 199 | } |
200 | ||
201 | #ifdef CONFIG_DPP3 | |
202 | if (auth->waiting_new_key) { | |
203 | wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key"); | |
204 | conn->on_tcp_tx_complete_gas_done = 0; | |
205 | return; | |
206 | } | |
207 | #endif /* CONFIG_DPP3 */ | |
185 | 208 | |
186 | 209 | if (auth->peer_version >= 2 && |
187 | 210 | auth->conf_resp_status == DPP_STATUS_OK) { |
238 | 261 | dpp_controller_rx, conn, NULL) == 0) |
239 | 262 | conn->read_eloop = 1; |
240 | 263 | if (conn->on_tcp_tx_complete_remove) { |
264 | if (conn->auth && conn->auth->connect_on_tx_status && | |
265 | conn->tcp_msg_sent && | |
266 | conn->tcp_msg_sent(conn->cb_ctx, conn->auth)) | |
267 | return 0; | |
241 | 268 | dpp_connection_remove(conn); |
242 | 269 | } else if (conn->auth && (conn->ctrl || conn->auth->configurator) && |
243 | 270 | conn->on_tcp_tx_complete_gas_done) { |
524 | 551 | /* TODO: Could send this to all configured Controllers. For now, |
525 | 552 | * only the first Controller is supported. */ |
526 | 553 | ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx); |
554 | } else if (type == DPP_PA_PKEX_EXCHANGE_REQ) { | |
555 | ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx); | |
527 | 556 | } else { |
528 | 557 | if (!r_bootstrap) |
529 | 558 | return -1; |
608 | 637 | eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ); |
609 | 638 | } |
610 | 639 | os_free(ctrl->configurator_params); |
640 | os_free(ctrl->pkex_code); | |
641 | os_free(ctrl->pkex_identifier); | |
611 | 642 | os_free(ctrl); |
612 | 643 | } |
613 | 644 | |
770 | 801 | wpa_msg(msg_ctx, MSG_INFO, |
771 | 802 | DPP_EVENT_CONF_SENT "wait_conn_status=1"); |
772 | 803 | wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); |
804 | auth->waiting_conn_status_result = 1; | |
773 | 805 | eloop_cancel_timeout( |
774 | 806 | dpp_controller_conn_status_result_wait_timeout, |
775 | 807 | conn, NULL); |
951 | 983 | res = dpp_tcp_send_msg(conn, conf); |
952 | 984 | wpabuf_free(conf); |
953 | 985 | return res; |
986 | } | |
987 | ||
988 | ||
989 | static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn, | |
990 | const u8 *hdr, const u8 *buf, | |
991 | size_t len) | |
992 | { | |
993 | struct dpp_controller *ctrl = conn->ctrl; | |
994 | ||
995 | if (!ctrl) | |
996 | return 0; | |
997 | ||
998 | wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request"); | |
999 | ||
1000 | /* TODO: Support multiple PKEX codes by iterating over all the enabled | |
1001 | * values here */ | |
1002 | ||
1003 | if (!ctrl->pkex_code || !ctrl->pkex_bi) { | |
1004 | wpa_printf(MSG_DEBUG, | |
1005 | "DPP: No PKEX code configured - ignore request"); | |
1006 | return 0; | |
1007 | } | |
1008 | ||
1009 | if (conn->pkex || conn->auth) { | |
1010 | wpa_printf(MSG_DEBUG, | |
1011 | "DPP: Already in PKEX/Authentication session - ignore new PKEX request"); | |
1012 | return 0; | |
1013 | } | |
1014 | ||
1015 | conn->pkex = dpp_pkex_rx_exchange_req(conn->msg_ctx, ctrl->pkex_bi, | |
1016 | NULL, NULL, | |
1017 | ctrl->pkex_identifier, | |
1018 | ctrl->pkex_code, | |
1019 | buf, len, true); | |
1020 | if (!conn->pkex) { | |
1021 | wpa_printf(MSG_DEBUG, | |
1022 | "DPP: Failed to process the request"); | |
1023 | return -1; | |
1024 | } | |
1025 | ||
1026 | return dpp_tcp_send_msg(conn, conn->pkex->exchange_resp); | |
1027 | } | |
1028 | ||
1029 | ||
1030 | static int dpp_controller_rx_pkex_exchange_resp(struct dpp_connection *conn, | |
1031 | const u8 *hdr, const u8 *buf, | |
1032 | size_t len) | |
1033 | { | |
1034 | struct dpp_pkex *pkex = conn->pkex; | |
1035 | struct wpabuf *msg; | |
1036 | int res; | |
1037 | ||
1038 | wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response"); | |
1039 | ||
1040 | if (!pkex || !pkex->initiator || pkex->exchange_done) { | |
1041 | wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); | |
1042 | return 0; | |
1043 | } | |
1044 | ||
1045 | msg = dpp_pkex_rx_exchange_resp(pkex, NULL, buf, len); | |
1046 | if (!msg) { | |
1047 | wpa_printf(MSG_DEBUG, "DPP: Failed to process the response"); | |
1048 | return -1; | |
1049 | } | |
1050 | ||
1051 | wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request"); | |
1052 | res = dpp_tcp_send_msg(conn, msg); | |
1053 | wpabuf_free(msg); | |
1054 | return res; | |
1055 | } | |
1056 | ||
1057 | ||
1058 | static int dpp_controller_rx_pkex_commit_reveal_req(struct dpp_connection *conn, | |
1059 | const u8 *hdr, | |
1060 | const u8 *buf, size_t len) | |
1061 | { | |
1062 | struct dpp_pkex *pkex = conn->pkex; | |
1063 | struct wpabuf *msg; | |
1064 | int res; | |
1065 | struct dpp_bootstrap_info *bi; | |
1066 | ||
1067 | wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request"); | |
1068 | ||
1069 | if (!pkex || pkex->initiator || !pkex->exchange_done) { | |
1070 | wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); | |
1071 | return 0; | |
1072 | } | |
1073 | ||
1074 | msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len); | |
1075 | if (!msg) { | |
1076 | wpa_printf(MSG_DEBUG, "DPP: Failed to process the request"); | |
1077 | return -1; | |
1078 | } | |
1079 | ||
1080 | wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response"); | |
1081 | res = dpp_tcp_send_msg(conn, msg); | |
1082 | wpabuf_free(msg); | |
1083 | if (res < 0) | |
1084 | return res; | |
1085 | bi = dpp_pkex_finish(conn->global, pkex, NULL, 0); | |
1086 | if (!bi) | |
1087 | return -1; | |
1088 | conn->pkex = NULL; | |
1089 | return 0; | |
1090 | } | |
1091 | ||
1092 | ||
1093 | static int | |
1094 | dpp_controller_rx_pkex_commit_reveal_resp(struct dpp_connection *conn, | |
1095 | const u8 *hdr, | |
1096 | const u8 *buf, size_t len) | |
1097 | { | |
1098 | struct dpp_pkex *pkex = conn->pkex; | |
1099 | int res; | |
1100 | struct dpp_bootstrap_info *bi; | |
1101 | ||
1102 | wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response"); | |
1103 | ||
1104 | if (!pkex || !pkex->initiator || !pkex->exchange_done) { | |
1105 | wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session"); | |
1106 | return 0; | |
1107 | } | |
1108 | ||
1109 | res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len); | |
1110 | if (res < 0) { | |
1111 | wpa_printf(MSG_DEBUG, "DPP: Failed to process the response"); | |
1112 | return res; | |
1113 | } | |
1114 | ||
1115 | bi = dpp_pkex_finish(conn->global, pkex, NULL, 0); | |
1116 | if (!bi) | |
1117 | return -1; | |
1118 | conn->pkex = NULL; | |
1119 | ||
1120 | if (!conn->pkex_done) | |
1121 | return -1; | |
1122 | return conn->pkex_done(conn->cb_ctx, conn, bi); | |
954 | 1123 | } |
955 | 1124 | |
956 | 1125 | |
1013 | 1182 | case DPP_PA_RECONFIG_AUTH_RESP: |
1014 | 1183 | return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos, |
1015 | 1184 | end - pos); |
1185 | case DPP_PA_PKEX_V1_EXCHANGE_REQ: | |
1186 | wpa_printf(MSG_DEBUG, | |
1187 | "DPP: Ignore PKEXv1 Exchange Request - not supported over TCP"); | |
1188 | return -1; | |
1189 | case DPP_PA_PKEX_EXCHANGE_REQ: | |
1190 | return dpp_controller_rx_pkex_exchange_req(conn, msg, pos, | |
1191 | end - pos); | |
1192 | case DPP_PA_PKEX_EXCHANGE_RESP: | |
1193 | return dpp_controller_rx_pkex_exchange_resp(conn, msg, pos, | |
1194 | end - pos); | |
1195 | case DPP_PA_PKEX_COMMIT_REVEAL_REQ: | |
1196 | return dpp_controller_rx_pkex_commit_reveal_req(conn, msg, pos, | |
1197 | end - pos); | |
1198 | case DPP_PA_PKEX_COMMIT_REVEAL_RESP: | |
1199 | return dpp_controller_rx_pkex_commit_reveal_resp(conn, msg, pos, | |
1200 | end - pos); | |
1016 | 1201 | default: |
1017 | 1202 | /* TODO: missing messages types */ |
1018 | 1203 | wpa_printf(MSG_DEBUG, |
1156 | 1341 | WLAN_PA_GAS_INITIAL_RESP); |
1157 | 1342 | } |
1158 | 1343 | |
1344 | if (!resp && auth->waiting_config && auth->peer_bi) { | |
1345 | char *buf = NULL, *name = ""; | |
1346 | char band[200], *b_pos, *b_end; | |
1347 | int i, res, *opclass = auth->e_band_support; | |
1348 | char *mud_url = "N/A"; | |
1349 | ||
1350 | wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready"); | |
1351 | if (auth->e_name) { | |
1352 | size_t e_len = os_strlen(auth->e_name); | |
1353 | ||
1354 | buf = os_malloc(e_len * 4 + 1); | |
1355 | if (buf) { | |
1356 | printf_encode(buf, len * 4 + 1, | |
1357 | (const u8 *) auth->e_name, e_len); | |
1358 | name = buf; | |
1359 | } | |
1360 | } | |
1361 | band[0] = '\0'; | |
1362 | b_pos = band; | |
1363 | b_end = band + sizeof(band); | |
1364 | for (i = 0; opclass && opclass[i]; i++) { | |
1365 | res = os_snprintf(b_pos, b_end - b_pos, "%s%d", | |
1366 | b_pos == band ? "" : ",", opclass[i]); | |
1367 | if (os_snprintf_error(b_end - b_pos, res)) { | |
1368 | *b_pos = '\0'; | |
1369 | break; | |
1370 | } | |
1371 | b_pos += res; | |
1372 | } | |
1373 | if (auth->e_mud_url) { | |
1374 | size_t e_len = os_strlen(auth->e_mud_url); | |
1375 | ||
1376 | if (!has_ctrl_char((const u8 *) auth->e_mud_url, e_len)) | |
1377 | mud_url = auth->e_mud_url; | |
1378 | } | |
1379 | wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_NEEDED | |
1380 | "peer=%d net_role=%s name=\"%s\" opclass=%s mud_url=%s", | |
1381 | auth->peer_bi->id, dpp_netrole_str(auth->e_netrole), | |
1382 | name, band, mud_url); | |
1383 | os_free(buf); | |
1384 | ||
1385 | conn->gas_comeback_in_progress = 1; | |
1386 | return dpp_tcp_send_comeback_delay(conn, | |
1387 | WLAN_PA_GAS_INITIAL_RESP); | |
1388 | } | |
1389 | ||
1159 | 1390 | return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp); |
1160 | 1391 | } |
1161 | 1392 | |
1220 | 1451 | |
1221 | 1452 | dpp_controller_start_gas_client(conn); |
1222 | 1453 | } |
1454 | ||
1455 | ||
1456 | #ifdef CONFIG_DPP3 | |
1457 | static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx) | |
1458 | { | |
1459 | struct dpp_connection *conn = eloop_ctx; | |
1460 | struct dpp_authentication *auth = conn->auth; | |
1461 | ||
1462 | if (!auth || !auth->waiting_new_key) | |
1463 | return; | |
1464 | ||
1465 | wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key"); | |
1466 | dpp_controller_start_gas_client(conn); | |
1467 | } | |
1468 | #endif /* CONFIG_DPP3 */ | |
1223 | 1469 | |
1224 | 1470 | |
1225 | 1471 | static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) |
1242 | 1488 | eloop_register_timeout(0, 0, dpp_tcp_build_csr, conn, NULL); |
1243 | 1489 | return 0; |
1244 | 1490 | } |
1491 | #ifdef CONFIG_DPP3 | |
1492 | if (res == -3) { | |
1493 | wpa_printf(MSG_DEBUG, "DPP: New protocol key needed"); | |
1494 | eloop_register_timeout(0, 0, dpp_tcp_build_new_key, conn, | |
1495 | NULL); | |
1496 | return 0; | |
1497 | } | |
1498 | #endif /* CONFIG_DPP3 */ | |
1245 | 1499 | if (res < 0) { |
1246 | 1500 | wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); |
1247 | 1501 | return -1; |
1533 | 1787 | conn->msg_ctx = ctrl->msg_ctx; |
1534 | 1788 | conn->cb_ctx = ctrl->cb_ctx; |
1535 | 1789 | conn->process_conf_obj = ctrl->process_conf_obj; |
1790 | conn->tcp_msg_sent = ctrl->tcp_msg_sent; | |
1536 | 1791 | conn->sock = fd; |
1537 | 1792 | conn->netrole = ctrl->netrole; |
1538 | 1793 | |
1558 | 1813 | } |
1559 | 1814 | |
1560 | 1815 | |
1561 | int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, | |
1562 | const struct hostapd_ip_addr *addr, int port, const char *name, | |
1563 | enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx, | |
1564 | int (*process_conf_obj)(void *ctx, | |
1565 | struct dpp_authentication *auth)) | |
1816 | int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex, | |
1817 | const struct hostapd_ip_addr *addr, int port, | |
1818 | void *msg_ctx, void *cb_ctx, | |
1819 | int (*pkex_done)(void *ctx, void *conn, | |
1820 | struct dpp_bootstrap_info *bi)) | |
1566 | 1821 | { |
1567 | 1822 | struct dpp_connection *conn; |
1568 | 1823 | struct sockaddr_storage saddr; |
1574 | 1829 | hostapd_ip_txt(addr, txt, sizeof(txt)), port); |
1575 | 1830 | if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen, |
1576 | 1831 | addr, port) < 0) { |
1832 | dpp_pkex_free(pkex); | |
1833 | return -1; | |
1834 | } | |
1835 | ||
1836 | conn = os_zalloc(sizeof(*conn)); | |
1837 | if (!conn) { | |
1838 | dpp_pkex_free(pkex); | |
1839 | return -1; | |
1840 | } | |
1841 | ||
1842 | conn->msg_ctx = msg_ctx; | |
1843 | conn->cb_ctx = cb_ctx; | |
1844 | conn->pkex_done = pkex_done; | |
1845 | conn->global = dpp; | |
1846 | conn->pkex = pkex; | |
1847 | conn->sock = socket(AF_INET, SOCK_STREAM, 0); | |
1848 | if (conn->sock < 0) | |
1849 | goto fail; | |
1850 | ||
1851 | if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { | |
1852 | wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", | |
1853 | strerror(errno)); | |
1854 | goto fail; | |
1855 | } | |
1856 | ||
1857 | if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) { | |
1858 | if (errno != EINPROGRESS) { | |
1859 | wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", | |
1860 | strerror(errno)); | |
1861 | goto fail; | |
1862 | } | |
1863 | ||
1864 | /* | |
1865 | * Continue connecting in the background; eloop will call us | |
1866 | * once the connection is ready (or failed). | |
1867 | */ | |
1868 | } | |
1869 | ||
1870 | if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, | |
1871 | dpp_conn_tx_ready, conn, NULL) < 0) | |
1872 | goto fail; | |
1873 | conn->write_eloop = 1; | |
1874 | ||
1875 | hdr = wpabuf_head(pkex->exchange_req); | |
1876 | end = hdr + wpabuf_len(pkex->exchange_req); | |
1877 | hdr += 2; /* skip Category and Actiom */ | |
1878 | pos = hdr + DPP_HDR_LEN; | |
1879 | conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos); | |
1880 | if (!conn->msg_out) | |
1881 | goto fail; | |
1882 | /* Message will be sent in dpp_conn_tx_ready() */ | |
1883 | ||
1884 | /* TODO: eloop timeout to clear a connection if it does not complete | |
1885 | * properly */ | |
1886 | dl_list_add(&dpp->tcp_init, &conn->list); | |
1887 | return 0; | |
1888 | fail: | |
1889 | dpp_connection_free(conn); | |
1890 | return -1; | |
1891 | } | |
1892 | ||
1893 | ||
1894 | static int dpp_tcp_auth_start(struct dpp_connection *conn, | |
1895 | struct dpp_authentication *auth) | |
1896 | { | |
1897 | const u8 *hdr, *pos, *end; | |
1898 | ||
1899 | hdr = wpabuf_head(auth->req_msg); | |
1900 | end = hdr + wpabuf_len(auth->req_msg); | |
1901 | hdr += 2; /* skip Category and Actiom */ | |
1902 | pos = hdr + DPP_HDR_LEN; | |
1903 | conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos); | |
1904 | if (!conn->msg_out) | |
1905 | return -1; | |
1906 | /* Message will be sent in dpp_conn_tx_ready() */ | |
1907 | return 0; | |
1908 | } | |
1909 | ||
1910 | ||
1911 | int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, | |
1912 | const struct hostapd_ip_addr *addr, int port, const char *name, | |
1913 | enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx, | |
1914 | int (*process_conf_obj)(void *ctx, | |
1915 | struct dpp_authentication *auth), | |
1916 | bool (*tcp_msg_sent)(void *ctx, | |
1917 | struct dpp_authentication *auth)) | |
1918 | { | |
1919 | struct dpp_connection *conn; | |
1920 | struct sockaddr_storage saddr; | |
1921 | socklen_t addrlen; | |
1922 | char txt[100]; | |
1923 | ||
1924 | wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d", | |
1925 | hostapd_ip_txt(addr, txt, sizeof(txt)), port); | |
1926 | if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen, | |
1927 | addr, port) < 0) { | |
1577 | 1928 | dpp_auth_deinit(auth); |
1578 | 1929 | return -1; |
1579 | 1930 | } |
1587 | 1938 | conn->msg_ctx = msg_ctx; |
1588 | 1939 | conn->cb_ctx = cb_ctx; |
1589 | 1940 | conn->process_conf_obj = process_conf_obj; |
1941 | conn->tcp_msg_sent = tcp_msg_sent; | |
1590 | 1942 | conn->name = os_strdup(name ? name : "Test"); |
1591 | 1943 | conn->netrole = netrole; |
1592 | 1944 | conn->global = dpp; |
1619 | 1971 | goto fail; |
1620 | 1972 | conn->write_eloop = 1; |
1621 | 1973 | |
1622 | hdr = wpabuf_head(auth->req_msg); | |
1623 | end = hdr + wpabuf_len(auth->req_msg); | |
1624 | hdr += 2; /* skip Category and Actiom */ | |
1625 | pos = hdr + DPP_HDR_LEN; | |
1626 | conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos); | |
1627 | if (!conn->msg_out) | |
1974 | if (dpp_tcp_auth_start(conn, auth) < 0) | |
1628 | 1975 | goto fail; |
1629 | /* Message will be sent in dpp_conn_tx_ready() */ | |
1630 | 1976 | |
1631 | 1977 | /* TODO: eloop timeout to clear a connection if it does not complete |
1632 | 1978 | * properly */ |
1635 | 1981 | fail: |
1636 | 1982 | dpp_connection_free(conn); |
1637 | 1983 | return -1; |
1984 | } | |
1985 | ||
1986 | ||
1987 | int dpp_tcp_auth(struct dpp_global *dpp, void *_conn, | |
1988 | struct dpp_authentication *auth, const char *name, | |
1989 | enum dpp_netrole netrole, | |
1990 | int (*process_conf_obj)(void *ctx, | |
1991 | struct dpp_authentication *auth), | |
1992 | bool (*tcp_msg_sent)(void *ctx, | |
1993 | struct dpp_authentication *auth)) | |
1994 | { | |
1995 | struct dpp_connection *conn = _conn; | |
1996 | ||
1997 | /* Continue with Authentication exchange on an existing TCP connection. | |
1998 | */ | |
1999 | conn->process_conf_obj = process_conf_obj; | |
2000 | conn->tcp_msg_sent = tcp_msg_sent; | |
2001 | os_free(conn->name); | |
2002 | conn->name = os_strdup(name ? name : "Test"); | |
2003 | conn->netrole = netrole; | |
2004 | conn->auth = auth; | |
2005 | ||
2006 | if (dpp_tcp_auth_start(conn, auth) < 0) | |
2007 | return -1; | |
2008 | ||
2009 | dpp_conn_tx_ready(conn->sock, conn, NULL); | |
2010 | return 0; | |
1638 | 2011 | } |
1639 | 2012 | |
1640 | 2013 | |
1663 | 2036 | ctrl->msg_ctx = config->msg_ctx; |
1664 | 2037 | ctrl->cb_ctx = config->cb_ctx; |
1665 | 2038 | ctrl->process_conf_obj = config->process_conf_obj; |
2039 | ctrl->tcp_msg_sent = config->tcp_msg_sent; | |
1666 | 2040 | |
1667 | 2041 | ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); |
1668 | 2042 | if (ctrl->sock < 0) |
1709 | 2083 | } |
1710 | 2084 | |
1711 | 2085 | |
2086 | int dpp_controller_set_params(struct dpp_global *dpp, | |
2087 | const char *configurator_params) | |
2088 | { | |
2089 | ||
2090 | if (!dpp || !dpp->controller) | |
2091 | return -1; | |
2092 | ||
2093 | if (configurator_params) { | |
2094 | char *val = os_strdup(configurator_params); | |
2095 | ||
2096 | if (!val) | |
2097 | return -1; | |
2098 | os_free(dpp->controller->configurator_params); | |
2099 | dpp->controller->configurator_params = val; | |
2100 | } else { | |
2101 | os_free(dpp->controller->configurator_params); | |
2102 | dpp->controller->configurator_params = NULL; | |
2103 | } | |
2104 | ||
2105 | return 0; | |
2106 | } | |
2107 | ||
2108 | ||
1712 | 2109 | void dpp_controller_stop(struct dpp_global *dpp) |
1713 | 2110 | { |
1714 | 2111 | if (dpp) { |
1788 | 2185 | } |
1789 | 2186 | |
1790 | 2187 | |
2188 | void dpp_controller_pkex_add(struct dpp_global *dpp, | |
2189 | struct dpp_bootstrap_info *bi, | |
2190 | const char *code, const char *identifier) | |
2191 | { | |
2192 | struct dpp_controller *ctrl = dpp->controller; | |
2193 | ||
2194 | if (!ctrl) | |
2195 | return; | |
2196 | ||
2197 | ctrl->pkex_bi = bi; | |
2198 | os_free(ctrl->pkex_code); | |
2199 | ctrl->pkex_code = code ? os_strdup(code) : NULL; | |
2200 | os_free(ctrl->pkex_identifier); | |
2201 | ctrl->pkex_identifier = identifier ? os_strdup(identifier) : NULL; | |
2202 | } | |
2203 | ||
2204 | ||
1791 | 2205 | void dpp_tcp_init_flush(struct dpp_global *dpp) |
1792 | 2206 | { |
1793 | 2207 | struct dpp_connection *conn, *tmp; |
1823 | 2237 | } |
1824 | 2238 | } |
1825 | 2239 | |
2240 | ||
2241 | bool dpp_tcp_conn_status_requested(struct dpp_global *dpp) | |
2242 | { | |
2243 | struct dpp_connection *conn; | |
2244 | ||
2245 | dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) { | |
2246 | if (conn->auth && conn->auth->conn_status_requested) | |
2247 | return true; | |
2248 | } | |
2249 | ||
2250 | return false; | |
2251 | } | |
2252 | ||
2253 | ||
2254 | static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn, | |
2255 | enum dpp_status_error result, | |
2256 | const u8 *ssid, size_t ssid_len, | |
2257 | const char *channel_list) | |
2258 | { | |
2259 | struct dpp_authentication *auth = conn->auth; | |
2260 | int res; | |
2261 | struct wpabuf *msg; | |
2262 | ||
2263 | auth->conn_status_requested = 0; | |
2264 | ||
2265 | msg = dpp_build_conn_status_result(auth, result, ssid, ssid_len, | |
2266 | channel_list); | |
2267 | if (!msg) { | |
2268 | dpp_connection_remove(conn); | |
2269 | return; | |
2270 | } | |
2271 | ||
2272 | res = dpp_tcp_send_msg(conn, msg); | |
2273 | wpabuf_free(msg); | |
2274 | ||
2275 | if (res < 0) { | |
2276 | dpp_connection_remove(conn); | |
2277 | return; | |
2278 | } | |
2279 | ||
2280 | /* This exchange will be terminated in the TX status handler */ | |
2281 | conn->on_tcp_tx_complete_remove = 1; | |
2282 | } | |
2283 | ||
2284 | ||
2285 | void dpp_tcp_send_conn_status(struct dpp_global *dpp, | |
2286 | enum dpp_status_error result, | |
2287 | const u8 *ssid, size_t ssid_len, | |
2288 | const char *channel_list) | |
2289 | { | |
2290 | struct dpp_connection *conn; | |
2291 | ||
2292 | dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) { | |
2293 | if (conn->auth && conn->auth->conn_status_requested) { | |
2294 | dpp_tcp_send_conn_status_msg(conn, result, ssid, | |
2295 | ssid_len, channel_list); | |
2296 | break; | |
2297 | } | |
2298 | } | |
2299 | } | |
2300 | ||
1826 | 2301 | #endif /* CONFIG_DPP2 */ |
1 | 1 | * Generic advertisement service (GAS) server |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2020, The Linux Foundation |
4 | * Copyright (c) 2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
17 | 18 | |
18 | 19 | |
19 | 20 | #define MAX_ADV_PROTO_ID_LEN 10 |
20 | #define GAS_QUERY_TIMEOUT 10 | |
21 | #define GAS_QUERY_TIMEOUT 60 | |
21 | 22 | |
22 | 23 | struct gas_server_handler { |
23 | 24 | struct dl_list list; |
25 | 26 | u8 adv_proto_id_len; |
26 | 27 | struct wpabuf * (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, |
27 | 28 | const u8 *query, size_t query_len, |
28 | u16 *comeback_delay); | |
29 | int *comeback_delay); | |
29 | 30 | void (*status_cb)(void *ctx, struct wpabuf *resp, int ok); |
30 | 31 | void *ctx; |
31 | 32 | struct gas_server *gas; |
41 | 42 | u8 dialog_token; |
42 | 43 | struct gas_server_handler *handler; |
43 | 44 | u16 comeback_delay; |
45 | bool initial_resp_sent; | |
44 | 46 | }; |
45 | 47 | |
46 | 48 | struct gas_server { |
85 | 87 | |
86 | 88 | |
87 | 89 | static void |
88 | gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, | |
90 | gas_server_send_resp(struct gas_server *gas, | |
89 | 91 | struct gas_server_response *response, |
90 | const u8 *da, int freq, u8 dialog_token, | |
91 | 92 | struct wpabuf *query_resp, u16 comeback_delay) |
92 | 93 | { |
93 | size_t max_len = (freq > 56160) ? 928 : 1400; | |
94 | struct gas_server_handler *handler = response->handler; | |
95 | size_t max_len = (response->freq > 56160) ? 928 : 1400; | |
94 | 96 | size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2; |
95 | 97 | size_t resp_frag_len; |
96 | 98 | struct wpabuf *resp; |
97 | 99 | |
98 | 100 | if (comeback_delay == 0 && !query_resp) { |
101 | dl_list_del(&response->list); | |
99 | 102 | gas_server_free_response(response); |
100 | 103 | return; |
101 | 104 | } |
102 | 105 | |
103 | response->freq = freq; | |
104 | response->handler = handler; | |
105 | os_memcpy(response->dst, da, ETH_ALEN); | |
106 | response->dialog_token = dialog_token; | |
107 | 106 | if (comeback_delay) { |
108 | 107 | /* Need more time to prepare the response */ |
109 | 108 | resp_frag_len = 0; |
118 | 117 | resp_frag_len = wpabuf_len(query_resp); |
119 | 118 | } |
120 | 119 | |
121 | resp = gas_build_initial_resp(dialog_token, WLAN_STATUS_SUCCESS, | |
120 | resp = gas_build_initial_resp(response->dialog_token, | |
121 | WLAN_STATUS_SUCCESS, | |
122 | 122 | comeback_delay, |
123 | 123 | handler->adv_proto_id_len + |
124 | 124 | resp_frag_len); |
125 | 125 | if (!resp) { |
126 | 126 | wpabuf_free(query_resp); |
127 | dl_list_del(&response->list); | |
127 | 128 | gas_server_free_response(response); |
128 | 129 | return; |
129 | 130 | } |
151 | 152 | } |
152 | 153 | response->offset = resp_frag_len; |
153 | 154 | response->resp = query_resp; |
154 | dl_list_add(&gas->responses, &response->list); | |
155 | gas->tx(gas->ctx, freq, da, resp, comeback_delay ? 2000 : 0); | |
155 | response->initial_resp_sent = true; | |
156 | gas->tx(gas->ctx, response->freq, response->dst, resp, | |
157 | comeback_delay ? 2000 : 0); | |
156 | 158 | wpabuf_free(resp); |
157 | 159 | eloop_register_timeout(GAS_QUERY_TIMEOUT, 0, |
158 | 160 | gas_server_response_timeout, response, NULL); |
222 | 224 | wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response); |
223 | 225 | dl_list_for_each(handler, &gas->handlers, struct gas_server_handler, |
224 | 226 | list) { |
225 | u16 comeback_delay = 0; | |
227 | int comeback_delay = 0; | |
226 | 228 | |
227 | 229 | if (adv_proto_len < 1 + handler->adv_proto_id_len || |
228 | 230 | os_memcmp(adv_proto + 1, handler->adv_proto_id, |
229 | 231 | handler->adv_proto_id_len) != 0) |
230 | 232 | continue; |
233 | ||
234 | response->freq = freq; | |
235 | response->handler = handler; | |
236 | os_memcpy(response->dst, sa, ETH_ALEN); | |
237 | response->dialog_token = dialog_token; | |
238 | dl_list_add(&gas->responses, &response->list); | |
231 | 239 | |
232 | 240 | wpa_printf(MSG_DEBUG, |
233 | 241 | "GAS: Calling handler for the requested Advertisement Protocol ID"); |
235 | 243 | query_req_len, &comeback_delay); |
236 | 244 | wpa_hexdump_buf(MSG_MSGDUMP, "GAS: Response from the handler", |
237 | 245 | resp); |
246 | if (comeback_delay < 0) { | |
247 | wpa_printf(MSG_DEBUG, | |
248 | "GAS: Handler requested short delay before sending out the initial response"); | |
249 | return 0; | |
250 | } | |
238 | 251 | if (comeback_delay) |
239 | 252 | wpa_printf(MSG_DEBUG, |
240 | 253 | "GAS: Handler requested comeback delay: %u TU", |
241 | 254 | comeback_delay); |
242 | gas_server_send_resp(gas, handler, response, sa, freq, | |
243 | dialog_token, resp, comeback_delay); | |
255 | gas_server_send_resp(gas, response, resp, comeback_delay); | |
244 | 256 | return 0; |
245 | 257 | } |
246 | 258 | |
483 | 495 | if (!response || response->resp) |
484 | 496 | return -1; |
485 | 497 | |
498 | if (!response->initial_resp_sent) { | |
499 | wpa_printf(MSG_DEBUG, "GAS: Send the delayed initial response"); | |
500 | gas_server_send_resp(gas, response, resp, 0); | |
501 | return 0; | |
502 | } | |
503 | ||
486 | 504 | response->resp = resp; |
505 | return 0; | |
506 | } | |
507 | ||
508 | ||
509 | int gas_server_set_comeback_delay(struct gas_server *gas, void *resp_ctx, | |
510 | u16 comeback_delay) | |
511 | { | |
512 | struct gas_server_response *tmp, *response = NULL; | |
513 | ||
514 | dl_list_for_each(tmp, &gas->responses, struct gas_server_response, | |
515 | list) { | |
516 | if (tmp == resp_ctx) { | |
517 | response = tmp; | |
518 | break; | |
519 | } | |
520 | } | |
521 | ||
522 | if (!response || response->initial_resp_sent) | |
523 | return -1; | |
524 | ||
525 | wpa_printf(MSG_DEBUG, | |
526 | "GAS: Send the delayed initial response with comeback delay %u", | |
527 | comeback_delay); | |
528 | gas_server_send_resp(gas, response, NULL, comeback_delay); | |
529 | ||
487 | 530 | return 0; |
488 | 531 | } |
489 | 532 | |
551 | 594 | struct wpabuf * |
552 | 595 | (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, |
553 | 596 | const u8 *query, size_t query_len, |
554 | u16 *comeback_delay), | |
597 | int *comeback_delay), | |
555 | 598 | void (*status_cb)(void *ctx, struct wpabuf *resp, |
556 | 599 | int ok), |
557 | 600 | void *ctx) |
1 | 1 | * Generic advertisement service (GAS) server |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2020, The Linux Foundation |
4 | * Copyright (c) 2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
24 | 25 | struct wpabuf * |
25 | 26 | (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, |
26 | 27 | const u8 *query, size_t query_len, |
27 | u16 *comeback_delay), | |
28 | int *comeback_delay), | |
28 | 29 | void (*status_cb)(void *ctx, struct wpabuf *resp, |
29 | 30 | int ok), |
30 | 31 | void *ctx); |
33 | 34 | int freq); |
34 | 35 | void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data, |
35 | 36 | size_t data_len, int ack); |
37 | int gas_server_set_comeback_delay(struct gas_server *gas, void *resp_ctx, | |
38 | u16 comeback_delay); | |
36 | 39 | int gas_server_set_resp(struct gas_server *gas, void *resp_ctx, |
37 | 40 | struct wpabuf *resp); |
38 | 41 | bool gas_server_response_sent(struct gas_server *gas, void *resp_ctx); |
761 | 761 | * various roam events to userspace. |
762 | 762 | * Applicable only for the STA mode. The attributes used with this command |
763 | 763 | * are defined in enum qca_wlan_vendor_attr_roam_events. |
764 | * | |
765 | * @QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG: Subcommand to set or reset the | |
766 | * rate mask config for a list of PHY types. Userspace shall provide an | |
767 | * array of the vendor attributes defined in | |
768 | * enum qca_wlan_vendor_attr_ratemask_params. | |
769 | * | |
770 | * @QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA: Multi-channel Concurrency (MCC) occurs | |
771 | * when two interfaces are active on the same band, using two different | |
772 | * home channels, and only supported by a single radio. In this scenario | |
773 | * the device must split the use of the radio between the two interfaces. | |
774 | * The percentage of time allocated to a given interface is the quota. | |
775 | * Depending on the configuration, the quota can either be fixed or | |
776 | * dynamic. | |
777 | * | |
778 | * When used as an event, the device will report the quota type, and for | |
779 | * all interfaces operating in MCC it will report the current quota. | |
780 | * When used as a command, the device can be configured for a specific | |
781 | * quota type, and in the case of a fixed quota, the quota to apply to one | |
782 | * of the interfaces. | |
783 | * | |
784 | * Applications can use the event to do TX bitrate control based on the | |
785 | * information, and can use the command to explicitly set the quota to | |
786 | * enhance performance in specific scenarios. | |
787 | * | |
788 | * The attributes used with this command are defined in | |
789 | * enum qca_wlan_vendor_attr_mcc_quota. | |
764 | 790 | */ |
765 | 791 | enum qca_nl80211_vendor_subcmds { |
766 | 792 | QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, |
954 | 980 | /* 201 - reserved for QCA */ |
955 | 981 | QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202, |
956 | 982 | QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203, |
983 | QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG = 204, | |
984 | QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA = 205, | |
957 | 985 | }; |
958 | 986 | |
959 | 987 | enum qca_wlan_vendor_attr { |
1570 | 1598 | * synchronous (in vendor command reply) to the request. Each TWT |
1571 | 1599 | * operation is specifically mentioned (against its respective |
1572 | 1600 | * documentation) to support either of these or both modes. |
1601 | * @QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI: Flag indicates | |
1602 | * that the driver requires add/del virtual interface path using the | |
1603 | * generic nl80211 commands for NDP interface create/delete and to | |
1604 | * register/unregister the netdev instead of creating/deleting the NDP | |
1605 | * interface using the vendor commands | |
1606 | * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE and | |
1607 | * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE. With the latest kernel | |
1608 | * (5.12 version onward), interface creation/deletion is not allowed using | |
1609 | * vendor commands as it leads to a deadlock while acquiring the RTNL_LOCK | |
1610 | * during the register/unregister of netdev. Create and delete NDP | |
1611 | * interface using NL80211_CMD_NEW_INTERFACE and NL80211_CMD_DEL_INTERFACE | |
1612 | * commands respectively if the driver advertises this capability set. | |
1573 | 1613 | * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits |
1574 | 1614 | */ |
1575 | 1615 | enum qca_wlan_vendor_features { |
1588 | 1628 | QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12, |
1589 | 1629 | QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13, |
1590 | 1630 | QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT = 14, |
1631 | QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI = 15, | |
1591 | 1632 | NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ |
1592 | 1633 | }; |
1593 | 1634 | |
4887 | 4928 | * ignored BSSIDs and accordingly clear the respective ones with the |
4888 | 4929 | * matching ID. |
4889 | 4930 | * |
4890 | * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned | |
4891 | * 32-bit value.Represents the number of whitelist SSIDs configured. | |
4892 | * | |
4893 | * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST: Nested attribute | |
4894 | * to carry the list of Whitelist SSIDs. | |
4895 | * | |
4896 | * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID: SSID (binary attribute, | |
4897 | * 0..32 octets). Represents the white list SSID. Whitelist SSIDs | |
4931 | * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS: Unsigned | |
4932 | * 32-bit value. Represents the number of allowlist SSIDs configured. | |
4933 | * | |
4934 | * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST: Nested attribute | |
4935 | * to carry the list of allowlist SSIDs. | |
4936 | * | |
4937 | * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID: SSID (binary attribute, | |
4938 | * 0..32 octets). Represents the allow list SSID. Allowlist SSIDs | |
4898 | 4939 | * represent the list of SSIDs to which the firmware/driver can consider |
4899 | 4940 | * to roam to. |
4900 | 4941 | * |
4932 | 4973 | * |
4933 | 4974 | * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE: Unsigned 32-bit |
4934 | 4975 | * value. 1-Enable, 0-Disable. Represents "Lazy" mode, where |
4935 | * firmware is hunting for a better BSSID or white listed SSID even though | |
4976 | * firmware is hunting for a better BSSID or allow listed SSID even though | |
4936 | 4977 | * the RSSI of the link is good. The parameters enabling the roaming are |
4937 | 4978 | * configured through the PARAM_A_BAND_XX attrbutes. |
4938 | 4979 | * |
4974 | 5015 | QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1, |
4975 | 5016 | QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2, |
4976 | 5017 | |
4977 | /* Attributes for wifi_set_ssid_white_list */ | |
4978 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3, | |
4979 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4, | |
4980 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5, | |
5018 | /* Attributes for wifi_set_ssid_allow_list */ | |
5019 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS = 3, | |
5020 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST = 4, | |
5021 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID = 5, | |
4981 | 5022 | |
4982 | 5023 | /* Attributes for set_roam_params */ |
4983 | 5024 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6, |
5012 | 5053 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1, |
5013 | 5054 | }; |
5014 | 5055 | |
5056 | /* old names for API compatibility */ | |
5057 | #define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS \ | |
5058 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS | |
5059 | #define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST \ | |
5060 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST | |
5061 | #define QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID \ | |
5062 | QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID | |
5063 | ||
5015 | 5064 | /* |
5016 | 5065 | * enum qca_wlan_vendor_roaming_subcmd: Referred by |
5017 | 5066 | * QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD. |
5018 | 5067 | * |
5019 | * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST: Sub command to | |
5020 | * configure the white list SSIDs. These are configured through | |
5068 | * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST: Sub command to | |
5069 | * configure the allow list SSIDs. These are configured through | |
5021 | 5070 | * the following attributes. |
5022 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS, | |
5023 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST, | |
5024 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID | |
5071 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_NUM_NETWORKS, | |
5072 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID_LIST, | |
5073 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALLOW_LIST_SSID | |
5025 | 5074 | * |
5026 | 5075 | * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS: Sub command to |
5027 | 5076 | * configure the Roam params. These parameters are evaluated on the GScan |
5037 | 5086 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID |
5038 | 5087 | * preference. |
5039 | 5088 | * |
5040 | * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs | |
5089 | * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID: Sets the list of BSSIDs | |
5041 | 5090 | * to ignore in roaming decision. Uses |
5042 | 5091 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list. |
5043 | 5092 | * |
5061 | 5110 | */ |
5062 | 5111 | enum qca_wlan_vendor_roaming_subcmd { |
5063 | 5112 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_INVALID = 0, |
5064 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST = 1, | |
5113 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST = 1, | |
5065 | 5114 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2, |
5066 | 5115 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM = 3, |
5067 | 5116 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS = 4, |
5068 | 5117 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PARAMS = 5, |
5069 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID = 6, | |
5118 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID = 6, | |
5070 | 5119 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET = 7, |
5071 | 5120 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET = 8, |
5072 | 5121 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR = 9, |
5073 | 5122 | }; |
5123 | ||
5124 | /* old names for API compatibility */ | |
5125 | #define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST \ | |
5126 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_ALLOW_LIST | |
5127 | #define QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID \ | |
5128 | QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID | |
5074 | 5129 | |
5075 | 5130 | enum qca_wlan_vendor_attr_gscan_config_params { |
5076 | 5131 | QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0, |
5430 | 5485 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID |
5431 | 5486 | = 43, |
5432 | 5487 | /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ |
5433 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID | |
5488 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID | |
5434 | 5489 | = 44, |
5435 | 5490 | |
5436 | 5491 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45, |
5438 | 5493 | /* Unsigned 32-bit value; a GSCAN Capabilities attribute. |
5439 | 5494 | * This is used to limit the maximum number of BSSIDs while sending |
5440 | 5495 | * the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with subcmd |
5441 | * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID and attribute | |
5496 | * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_DENYLIST_BSSID and attribute | |
5442 | 5497 | * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID. |
5443 | 5498 | */ |
5444 | QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46, | |
5499 | QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID = 46, | |
5445 | 5500 | |
5446 | 5501 | /* keep last */ |
5447 | 5502 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST, |
5448 | 5503 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX = |
5449 | 5504 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1, |
5450 | 5505 | }; |
5506 | ||
5507 | /* old names for API compatibility */ | |
5508 | #define QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID \ | |
5509 | QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_ALLOWLISTED_SSID | |
5510 | #define QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID \ | |
5511 | QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_DENYLISTED_BSSID | |
5451 | 5512 | |
5452 | 5513 | enum qca_wlan_vendor_attr_pno_config_params { |
5453 | 5514 | QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0, |
5578 | 5639 | * current channel. |
5579 | 5640 | */ |
5580 | 5641 | QCA_WLAN_VENDOR_ACS_SELECT_REASON_JAMMER_INTERFERENCE, |
5642 | /* Represents the reason that ACS triggered by AFC */ | |
5643 | QCA_WLAN_VENDOR_ACS_SELECT_REASON_AFC_TRIGGER, | |
5581 | 5644 | }; |
5582 | 5645 | |
5583 | 5646 | /** |
5785 | 5848 | */ |
5786 | 5849 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 = 13, |
5787 | 5850 | |
5851 | /* | |
5852 | * 16-bit attribute of bits indicating the AP power modes supported by | |
5853 | * the channel (u16). | |
5854 | * Note: Currently, only 3 bits are used in the attribute and each bit | |
5855 | * corresponds to the power mode mentioned in enum | |
5856 | * qca_wlan_vendor_external_acs_chan_power_mode and a given bit is | |
5857 | * set if the associated mode is supported. | |
5858 | */ | |
5859 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_SUPP_POWER_MODES | |
5860 | = 14, | |
5861 | /* Array of nested attributes for each power mode. It takes attr as | |
5862 | * defined in enum | |
5863 | * qca_wlan_vendor_external_acs_event_chan_power_info_attr. | |
5864 | */ | |
5865 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR = 15, | |
5788 | 5866 | /* keep last */ |
5789 | 5867 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST, |
5790 | 5868 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX = |
5791 | 5869 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST - 1, |
5870 | }; | |
5871 | ||
5872 | /** | |
5873 | * qca_wlan_vendor_external_acs_chan_power_mode - Specifies the valid | |
5874 | * values that the vendor external ACS channel power attribute | |
5875 | * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_MODE can | |
5876 | * take. | |
5877 | * @QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_LOW_POWER: Low power/Indoor mode | |
5878 | * @QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_STANDARD_POWER: Standard power mode | |
5879 | * @QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_VERY_LOW_POWER: Very low power mode | |
5880 | */ | |
5881 | enum qca_wlan_vendor_external_acs_chan_power_level { | |
5882 | QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_LOW_POWER = 0, | |
5883 | QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_STANDARD_POWER = 1, | |
5884 | QCA_WLAN_VENDOR_EXTERNAL_ACS_CHAN_VERY_LOW_POWER = 2, | |
5885 | }; | |
5886 | ||
5887 | /** | |
5888 | * qca_wlan_vendor_external_acs_event_chan_power_info_attr: Represents nested | |
5889 | * attributes for power mode type and power values corresponding to that. | |
5890 | * These attributes are sent as part of | |
5891 | * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR. | |
5892 | */ | |
5893 | enum qca_wlan_vendor_external_acs_event_chan_power_info_attr { | |
5894 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_INVALID = 0, | |
5895 | /* | |
5896 | * Power mode (u8) takes the values defined in enum | |
5897 | * qca_wlan_vendor_external_acs_chan_power_mode | |
5898 | */ | |
5899 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_MODE | |
5900 | = 1, | |
5901 | /* | |
5902 | * Indicates if power value is a PSD/EIRP value (flag). If flag is | |
5903 | * present, it indicates a PSD value. | |
5904 | */ | |
5905 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_PSD_FLAG = 2, | |
5906 | /* | |
5907 | * Power value (u32) PSD/EIRP as indicated by | |
5908 | * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_PSD_FLAG, | |
5909 | * for power mode corresponding to the | |
5910 | * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_MODE. | |
5911 | * Units for PSD - dBm/MHz | |
5912 | * Units for EIRP - dBm | |
5913 | */ | |
5914 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_POWER_VALUE | |
5915 | = 3, | |
5916 | /* keep last */ | |
5917 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_LAST, | |
5918 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_MAX = | |
5919 | QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_POWER_INFO_ATTR_LAST - 1, | |
5792 | 5920 | }; |
5793 | 5921 | |
5794 | 5922 | /** |
5815 | 5943 | * bit 3 set: channel should be excluded in GO negotiation |
5816 | 5944 | */ |
5817 | 5945 | QCA_WLAN_VENDOR_ATTR_PCL_FLAG = 4, |
5946 | ||
5947 | /* Keep last */ | |
5948 | QCA_WLAN_VENDOR_ATTR_PCL_LAST, | |
5949 | QCA_WLAN_VENDOR_ATTR_PCL_MAX = QCA_WLAN_VENDOR_ATTR_PCL_LAST - 1 | |
5818 | 5950 | }; |
5819 | 5951 | |
5820 | 5952 | /** |
5877 | 6009 | * qca_wlan_vendor_attr_rropavail_info. |
5878 | 6010 | */ |
5879 | 6011 | QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_RROPAVAIL_INFO = 14, |
6012 | /* Flag attribute to indicate if driver supports 6 GHz AFC trigger | |
6013 | * for External ACS | |
6014 | */ | |
6015 | QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AFC_CAPABILITY = 15, | |
5880 | 6016 | |
5881 | 6017 | /* keep last */ |
5882 | 6018 | QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST, |
6480 | 6616 | * for the current operating bandwidth. |
6481 | 6617 | */ |
6482 | 6618 | QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH = 30, |
6619 | /* Spectral FFT recapture flag attribute, to enable FFT recapture. | |
6620 | * Recapture can only be enabled for scan period greater than 52 us. | |
6621 | * If this attribute is enabled, re-triggers will be enabled when AGC | |
6622 | * gain changes. | |
6623 | */ | |
6624 | QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE = 31, | |
6483 | 6625 | |
6484 | 6626 | QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST, |
6485 | 6627 | QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX = |
6815 | 6957 | }; |
6816 | 6958 | |
6817 | 6959 | /** |
6960 | * enum qca_wlan_vendor_flush_pending_policy: Represents values for | |
6961 | * the policy to flush pending frames, configured via | |
6962 | * %QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING. This enumeration defines the | |
6963 | * valid values for %QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY. | |
6964 | * | |
6965 | * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE: This value clears all | |
6966 | * the flush policy configured before. This command basically disables the | |
6967 | * flush config set by the user. | |
6968 | * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE: This value configures | |
6969 | * the flush policy to be immediate. All pending packets for the peer/TID are | |
6970 | * flushed when this command/policy is received. | |
6971 | * @QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END: This value configures | |
6972 | * the flush policy to the end of TWT SP. All pending packets for the peer/TID | |
6973 | * are flushed when the end of TWT SP is reached. | |
6974 | */ | |
6975 | enum qca_wlan_vendor_flush_pending_policy { | |
6976 | QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_NONE = 0, | |
6977 | QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_IMMEDIATE = 1, | |
6978 | QCA_WLAN_VENDOR_FLUSH_PENDING_POLICY_TWT_SP_END = 2, | |
6979 | }; | |
6980 | ||
6981 | /** | |
6818 | 6982 | * enum qca_wlan_vendor_attr_flush_pending - Attributes for |
6819 | 6983 | * flushing pending traffic in firmware. |
6820 | 6984 | * |
6822 | 6986 | * @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending |
6823 | 6987 | * packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK, |
6824 | 6988 | * AC_VI, AC_VO respectively. Set the corresponding bit to 1 to |
6825 | * flush packets with access category. | |
6989 | * flush packets with access category. This is optional. See below. | |
6990 | * @QCA_WLAN_VENDOR_ATTR_TID_MASK: Configure TID mask of the pending packets. | |
6991 | * It is a u32 value with bit 0-7 representing TID 0-7. Set corresponding | |
6992 | * bit to 1 to act upon the TID. This is optional. Either this attribute or | |
6993 | * %QCA_WLAN_VENDOR_ATTR_AC must be provided. If both are provided, | |
6994 | * %QCA_WLAN_VENDOR_ATTR_TID_MASK takes precedence. If neither are provided | |
6995 | * it is an error. | |
6996 | * @QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY: Policy of flushing the pending | |
6997 | * packets corresponding to the peer/TID provided. It is a u32 value, | |
6998 | * represented by %enum qca_wlan_vendor_flush_pending_policy. This | |
6999 | * value is honored only when TID mask is provided. This is not honored when AC | |
7000 | * mask is provided. | |
6826 | 7001 | */ |
6827 | 7002 | enum qca_wlan_vendor_attr_flush_pending { |
6828 | 7003 | QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0, |
6829 | 7004 | QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1, |
6830 | 7005 | QCA_WLAN_VENDOR_ATTR_AC = 2, |
7006 | QCA_WLAN_VENDOR_ATTR_TID_MASK = 3, | |
7007 | QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_POLICY = 4, | |
6831 | 7008 | |
6832 | 7009 | /* keep last */ |
6833 | 7010 | QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST, |
6944 | 7121 | * |
6945 | 7122 | * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL: |
6946 | 7123 | * Default WLAN operation level which throughput orientated. |
6947 | * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE: | |
6948 | * Use moderate level to improve latency by limit scan duration. | |
7124 | * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR: | |
7125 | * Use XR level to benefit XR (extended reality) application to achieve | |
7126 | * latency and power by via constraint scan/roaming/adaptive PS. | |
6949 | 7127 | * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW: |
6950 | * Use low latency level to benifit application like concurrent | |
7128 | * Use low latency level to benefit application like concurrent | |
6951 | 7129 | * downloading or video streaming via constraint scan/adaptive PS. |
6952 | 7130 | * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW: |
6953 | 7131 | * Use ultra low latency level to benefit for gaming/voice |
6956 | 7134 | enum qca_wlan_vendor_attr_config_latency_level { |
6957 | 7135 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0, |
6958 | 7136 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1, |
6959 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2, | |
7137 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR = 2, | |
7138 | /* legacy name */ | |
7139 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = | |
7140 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR, | |
6960 | 7141 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3, |
6961 | 7142 | QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4, |
6962 | 7143 | |
7268 | 7449 | * 1:support 0:not support |
7269 | 7450 | */ |
7270 | 7451 | QCA_WLAN_VENDOR_ATTR_PEER_NDPE_SUPPORT = 30, |
7452 | /* As per Wi-Fi Aware Specification v3.2 Service Id is the first | |
7453 | * 48 bits of the SHA-256 hash of the Service Name. | |
7454 | * A lower-case representation of the Service Name shall be used to | |
7455 | * calculate the Service ID. | |
7456 | * Array of u8: length is 6 bytes | |
7457 | * This attribute is used and optional for ndp indication. | |
7458 | */ | |
7459 | QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_ID = 31, | |
7271 | 7460 | |
7272 | 7461 | /* keep last */ |
7273 | 7462 | QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST, |
7277 | 7466 | |
7278 | 7467 | enum qca_wlan_ndp_sub_cmd { |
7279 | 7468 | QCA_WLAN_VENDOR_ATTR_NDP_INVALID = 0, |
7280 | /* Command to create a NAN data path interface */ | |
7469 | /* Command to create a NAN data path interface. | |
7470 | * This command was initially designed to both create and start a NAN | |
7471 | * data path interface. However, changes to Linux 5.12 no longer allow | |
7472 | * interface creation via vendor commands. When the driver advertises | |
7473 | * QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI | |
7474 | * userspace must explicitly first create the interface using | |
7475 | * NL80211_CMD_NEW_INTERFACE before subsequently invoking this command | |
7476 | * to start the interface. | |
7477 | */ | |
7281 | 7478 | QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE = 1, |
7282 | /* Command to delete a NAN data path interface */ | |
7479 | /* Command to delete a NAN data path interface. | |
7480 | * This command was initially designed to both stop and delete a NAN | |
7481 | * data path interface. However, changes to Linux 5.12 no longer allow | |
7482 | * interface deletion via vendor commands. When the driver advertises | |
7483 | * QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI | |
7484 | * userspace must explicitly delete the interface using | |
7485 | * NL80211_CMD_DEL_INTERFACE after calling this command. | |
7486 | */ | |
7283 | 7487 | QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE = 2, |
7284 | 7488 | /* Command to initiate a NAN data path session */ |
7285 | 7489 | QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST = 3, |
8497 | 8701 | * peer. Refers the enum qca_wlan_vendor_attr_twt_capability. It's a synchronous |
8498 | 8702 | * operation. |
8499 | 8703 | * |
8500 | * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is | |
8704 | * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmware is | |
8501 | 8705 | * ready for a new TWT session setup after it issued a TWT teardown. |
8502 | 8706 | * |
8503 | 8707 | * @QCA_WLAN_TWT_SET_PARAM: Configure TWT related parameters. Required |
8504 | 8708 | * parameters are obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refer |
8505 | 8709 | * the enum qca_wlan_vendor_attr_twt_set_param. |
8710 | * | |
8711 | * @QCA_WLAN_TWT_NOTIFY: Used to notify userspace about changes in TWT | |
8712 | * related information for example TWT required bit in AP capabilities etc. | |
8713 | * The reason for the notification is sent using | |
8714 | * QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS. | |
8506 | 8715 | */ |
8507 | 8716 | enum qca_wlan_twt_operation { |
8508 | 8717 | QCA_WLAN_TWT_SET = 0, |
8516 | 8725 | QCA_WLAN_TWT_GET_CAPABILITIES = 8, |
8517 | 8726 | QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9, |
8518 | 8727 | QCA_WLAN_TWT_SET_PARAM = 10, |
8728 | QCA_WLAN_TWT_NOTIFY = 11, | |
8519 | 8729 | }; |
8520 | 8730 | |
8521 | 8731 | /** |
8532 | 8742 | * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume, |
8533 | 8743 | * enum qca_wlan_vendor_attr_twt_set_param, or |
8534 | 8744 | * enum qca_wlan_vendor_attr_twt_stats based on the operation. |
8745 | * | |
8746 | * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS: Size is u8, mandatory when | |
8747 | * QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to QCA_WLAN_TWT_NOTIFY. | |
8748 | * The values used by this attribute are defined in | |
8749 | * enum qca_wlan_vendor_twt_status. | |
8535 | 8750 | */ |
8536 | 8751 | enum qca_wlan_vendor_attr_config_twt { |
8537 | 8752 | QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0, |
8538 | 8753 | QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION = 1, |
8539 | 8754 | QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS = 2, |
8755 | QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_NOTIFY_STATUS = 3, | |
8540 | 8756 | |
8541 | 8757 | /* keep last */ |
8542 | 8758 | QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST, |
9012 | 9228 | * QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE: The driver requested to |
9013 | 9229 | * terminate an existing TWT session on power save exit request from userspace. |
9014 | 9230 | * Used on the TWT_TERMINATE notification from the driver/firmware. |
9231 | * @QCA_WLAN_VENDOR_TWT_STATUS_TWT_REQUIRED: The peer has set the TWT | |
9232 | * required bit in its capabilities. | |
9233 | * @QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_REQUIRED: The peer has cleared | |
9234 | * the TWT required bit(1->0) in its capabilities. | |
9015 | 9235 | */ |
9016 | 9236 | enum qca_wlan_vendor_twt_status { |
9017 | 9237 | QCA_WLAN_VENDOR_TWT_STATUS_OK = 0, |
9037 | 9257 | QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20, |
9038 | 9258 | QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS = 21, |
9039 | 9259 | QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE = 22, |
9260 | QCA_WLAN_VENDOR_TWT_STATUS_TWT_REQUIRED = 23, | |
9261 | QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_REQUIRED = 24, | |
9040 | 9262 | }; |
9041 | 9263 | |
9042 | 9264 | /** |
9882 | 10104 | * has priority over BT_A2DP and ZB_HIGH. |
9883 | 10105 | * 3: BT_A2DP has priority over ZB_HIGH. |
9884 | 10106 | */ |
9885 | ||
9886 | 10107 | enum qca_vendor_attr_coex_config_three_way { |
9887 | 10108 | QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0, |
9888 | 10109 | QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1, |
11518 | 11739 | }; |
11519 | 11740 | |
11520 | 11741 | /** |
11742 | * enum qca_wlan_vendor_mcc_quota_type: MCC channel time quota type | |
11743 | * | |
11744 | * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR: In the event, it indicates that the | |
11745 | * target exited MCC state and cleared the quota information. In the | |
11746 | * command it clears MCC quota setting and restores adaptive scheduling. | |
11747 | * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED: Channel time quota is fixed and | |
11748 | * will not be changed. | |
11749 | * @QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC: Channel time quota is dynamic | |
11750 | * and the target may change the quota based on the data activity. | |
11751 | */ | |
11752 | enum qca_wlan_vendor_mcc_quota_type { | |
11753 | QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR = 0, | |
11754 | QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED = 1, | |
11755 | QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_DYNAMIC = 2, | |
11756 | }; | |
11757 | ||
11758 | /** | |
11759 | * enum qca_wlan_vendor_attr_mcc_quota: Used by the vendor event | |
11760 | * QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA to indicate MCC channel | |
11761 | * quota information or as a command to set the required MCC quota for an | |
11762 | * interface. | |
11763 | * | |
11764 | * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE: u32 attribute. | |
11765 | * The type is defined in enum qca_wlan_vendor_mcc_quota_type. | |
11766 | * In a command this specifies the MCC quota type to be set for the interface. | |
11767 | * In an event this provides the current quota type in force. | |
11768 | * This is required in a command and an event. | |
11769 | * | |
11770 | * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES: Nested attribute to carry | |
11771 | * the list of channel quota entries. | |
11772 | * In an event each entry contains the frequency and respective time quota for | |
11773 | * all the MCC interfaces. | |
11774 | * In a command it specifies the interface index and respective time quota. | |
11775 | * In a command only one entry (ifindex, quota pair) may be specified. | |
11776 | * | |
11777 | * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ: u32 attribute. | |
11778 | * Channel frequency in MHz. This is present only in an event. | |
11779 | * | |
11780 | * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE: u32 attribute. | |
11781 | * Channel time quota expressed as percentage. | |
11782 | * This is present in an event and a command. | |
11783 | * In an command, the user shall specify the quota to be allocated for the | |
11784 | * interface represented by %QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX. | |
11785 | * In an event this provides the existing quota for the channel. | |
11786 | * | |
11787 | * @QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX: u32 attribute. | |
11788 | * Specifies the interface index (netdev) for which the corresponding | |
11789 | * configurations are applied. This is required in a command only. Only one | |
11790 | * interface index may be specified. If not specified, the configuration is | |
11791 | * rejected. | |
11792 | */ | |
11793 | enum qca_wlan_vendor_attr_mcc_quota { | |
11794 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_INVALID = 0, | |
11795 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE = 1, | |
11796 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES = 2, | |
11797 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ = 3, | |
11798 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE = 4, | |
11799 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX = 5, | |
11800 | ||
11801 | /* keep last */ | |
11802 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST, | |
11803 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX = | |
11804 | QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_LAST - 1, | |
11805 | }; | |
11806 | ||
11807 | /** | |
11521 | 11808 | * enum qca_wlan_vendor_attr_mdns_offload - Attributes used by |
11522 | 11809 | * %QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD vendor command. |
11523 | 11810 | * |
11611 | 11898 | * the Beacon frames obtained during the scan (off channel and connected |
11612 | 11899 | * channel), when in connected state. |
11613 | 11900 | */ |
11614 | ||
11615 | 11901 | enum qca_wlan_vendor_monitor_mgmt_frame_type { |
11616 | 11902 | QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0), |
11617 | 11903 | /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set |
11671 | 11957 | * expecting the connected BSS's Beacon frames to be sent on the monitor |
11672 | 11958 | * interface at this specific interval. |
11673 | 11959 | */ |
11674 | enum qca_wlan_vendor_attr_set_monitor_mode | |
11675 | { | |
11960 | enum qca_wlan_vendor_attr_set_monitor_mode { | |
11676 | 11961 | QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0, |
11677 | 11962 | QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1, |
11678 | 11963 | QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2, |
11824 | 12109 | * u32 values. List of frequencies in MHz considered for a roam scan. |
11825 | 12110 | * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. |
11826 | 12111 | */ |
11827 | ||
11828 | enum qca_wlan_vendor_attr_roam_events | |
11829 | { | |
12112 | enum qca_wlan_vendor_attr_roam_events { | |
11830 | 12113 | QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0, |
11831 | 12114 | QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1, |
11832 | 12115 | QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2, |
11843 | 12126 | QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST -1, |
11844 | 12127 | }; |
11845 | 12128 | |
12129 | /** | |
12130 | * enum qca_wlan_ratemask_params_type - Rate mask config type | |
12131 | * | |
12132 | * @QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM: CCK/OFDM rate mask config | |
12133 | * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HT: HT rate mask config | |
12134 | * @QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT: VHT rate mask config | |
12135 | * @QCA_WLAN_RATEMASK_PARAMS_TYPE_HE: HE rate mask config | |
12136 | */ | |
12137 | enum qca_wlan_ratemask_params_type { | |
12138 | QCA_WLAN_RATEMASK_PARAMS_TYPE_CCK_OFDM = 0, | |
12139 | QCA_WLAN_RATEMASK_PARAMS_TYPE_HT = 1, | |
12140 | QCA_WLAN_RATEMASK_PARAMS_TYPE_VHT = 2, | |
12141 | QCA_WLAN_RATEMASK_PARAMS_TYPE_HE = 3, | |
12142 | }; | |
12143 | ||
12144 | /** | |
12145 | * enum qca_wlan_vendor_attr_ratemask_params - Used by the | |
12146 | * vendor command QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG. | |
12147 | * This is used to set the rate mask value to be used in rate selection. | |
12148 | * | |
12149 | * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST: | |
12150 | * Array of nested containing attributes | |
12151 | * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE and | |
12152 | * QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP. | |
12153 | * | |
12154 | * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE: u8, represents | |
12155 | * the different PHY types to which the rate mask config is to be applied. | |
12156 | * The values for this attribute are referred from enum | |
12157 | * qca_wlan_vendor_ratemask_params_type. | |
12158 | * | |
12159 | * @QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP: binary, rate mask bitmap. | |
12160 | * A bit value of 1 represents rate is enabled and a value of 0 | |
12161 | * represents rate is disabled. | |
12162 | * For HE targets, 12 bits correspond to one NSS setting. | |
12163 | * b0-13 => NSS1, MCS 0-13 | |
12164 | * b14-27 => NSS2, MCS 0-13 and so on for other NSS. | |
12165 | * For VHT targets, 10 bits correspond to one NSS setting. | |
12166 | * b0-9 => NSS1, MCS 0-9 | |
12167 | * b10-19 => NSS2, MCS 0-9 and so on for other NSS. | |
12168 | * For HT targets, 8 bits correspond to one NSS setting. | |
12169 | * b0-7 => NSS1, MCS 0-7 | |
12170 | * b8-15 => NSS2, MCS 0-7 and so on for other NSS. | |
12171 | * For OFDM/CCK targets, 8 bits correspond to one NSS setting. | |
12172 | */ | |
12173 | enum qca_wlan_vendor_attr_ratemask_params { | |
12174 | QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_INVALID = 0, | |
12175 | QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST = 1, | |
12176 | QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE = 2, | |
12177 | QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP = 3, | |
12178 | ||
12179 | /* keep last */ | |
12180 | QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST, | |
12181 | QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX = | |
12182 | QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_AFTER_LAST - 1, | |
12183 | }; | |
12184 | ||
11846 | 12185 | #endif /* QCA_VENDOR_H */ |
8 | 8 | #define GIT_VERSION_STR_POSTFIX "" |
9 | 9 | #endif /* GIT_VERSION_STR_POSTFIX */ |
10 | 10 | |
11 | #define VERSION_STR "2.10" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX | |
11 | #define VERSION_STR "2.11-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX | |
12 | 12 | |
13 | 13 | #endif /* VERSION_H */ |
1598 | 1598 | "%s: invalid group cipher 0x%x (%08x)", |
1599 | 1599 | __func__, data->group_cipher, |
1600 | 1600 | WPA_GET_BE32(pos)); |
1601 | #ifdef CONFIG_NO_TKIP | |
1602 | if (RSN_SELECTOR_GET(pos) == RSN_CIPHER_SUITE_TKIP) { | |
1603 | wpa_printf(MSG_DEBUG, | |
1604 | "%s: TKIP as group cipher not supported in CONFIG_NO_TKIP=y build", | |
1605 | __func__); | |
1606 | } | |
1607 | #endif /* CONFIG_NO_TKIP */ | |
1601 | 1608 | return -1; |
1602 | 1609 | } |
1603 | 1610 | pos += RSN_SELECTOR_LEN; |
211 | 211 | #define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT " |
212 | 212 | #define DPP_EVENT_CSR "DPP-CSR " |
213 | 213 | #define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX " |
214 | #define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED " | |
214 | 215 | |
215 | 216 | /* MESH events */ |
216 | 217 | #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " |
361 | 362 | #define P2P_EVENT_LISTEN_OFFLOAD_STOP "P2P-LISTEN-OFFLOAD-STOPPED " |
362 | 363 | #define P2P_LISTEN_OFFLOAD_STOP_REASON "P2P-LISTEN-OFFLOAD-STOP-REASON " |
363 | 364 | |
365 | /* BSS Transition Management Query frame received */ | |
366 | #define BSS_TM_QUERY "BSS-TM-QUERY " | |
367 | ||
364 | 368 | /* BSS Transition Management Response frame received */ |
365 | 369 | #define BSS_TM_RESP "BSS-TM-RESP " |
366 | 370 |
118 | 118 | return ASN1_STRING_data((ASN1_STRING *) x); |
119 | 119 | } |
120 | 120 | #endif /* OpenSSL version < 1.1.0 */ |
121 | ||
122 | ||
123 | #if OPENSSL_VERSION_NUMBER < 0x10101000L | |
124 | static int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, | |
125 | BIGNUM *b, BN_CTX *ctx) | |
126 | { | |
127 | return EC_GROUP_get_curve_GFp(group, p, a, b, ctx); | |
128 | } | |
129 | #endif /* OpenSSL version < 1.1.1 */ | |
121 | 130 | |
122 | 131 | |
123 | 132 | void openssl_load_legacy_provider(void) |
1751 | 1760 | e->b = BN_new(); |
1752 | 1761 | if (e->group == NULL || e->bnctx == NULL || e->prime == NULL || |
1753 | 1762 | e->order == NULL || e->a == NULL || e->b == NULL || |
1754 | !EC_GROUP_get_curve_GFp(e->group, e->prime, e->a, e->b, e->bnctx) || | |
1763 | !EC_GROUP_get_curve(e->group, e->prime, e->a, e->b, e->bnctx) || | |
1755 | 1764 | !EC_GROUP_get_order(e->group, e->order, e->bnctx)) { |
1756 | 1765 | crypto_ec_deinit(e); |
1757 | 1766 | e = NULL; |
2776 | 2785 | } |
2777 | 2786 | |
2778 | 2787 | |
2779 | struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, | |
2780 | const u8 *data, size_t len) | |
2781 | { | |
2788 | static int openssl_evp_pkey_ec_prime_len(struct crypto_ec_key *key) | |
2789 | { | |
2790 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L | |
2791 | char gname[50]; | |
2792 | int nid; | |
2793 | EC_GROUP *group; | |
2794 | BIGNUM *prime = NULL; | |
2795 | int prime_len = -1; | |
2796 | ||
2797 | if (EVP_PKEY_get_group_name((EVP_PKEY *) key, gname, sizeof(gname), | |
2798 | NULL) != 1) | |
2799 | return -1; | |
2800 | nid = OBJ_txt2nid(gname); | |
2801 | group = EC_GROUP_new_by_curve_name(nid); | |
2802 | prime = BN_new(); | |
2803 | if (!group || !prime) | |
2804 | return -1; | |
2805 | if (EC_GROUP_get_curve(group, prime, NULL, NULL, NULL) == 1) | |
2806 | prime_len = BN_num_bytes(prime); | |
2807 | EC_GROUP_free(group); | |
2808 | BN_free(prime); | |
2809 | return prime_len; | |
2810 | #else | |
2782 | 2811 | const EC_GROUP *group; |
2783 | 2812 | const EC_KEY *eckey; |
2784 | 2813 | BIGNUM *prime = NULL; |
2814 | int prime_len = -1; | |
2815 | ||
2816 | eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); | |
2817 | if (!eckey) | |
2818 | goto fail; | |
2819 | group = EC_KEY_get0_group(eckey); | |
2820 | prime = BN_new(); | |
2821 | if (!prime || !group || | |
2822 | !EC_GROUP_get_curve(group, prime, NULL, NULL, NULL)) | |
2823 | goto fail; | |
2824 | prime_len = BN_num_bytes(prime); | |
2825 | fail: | |
2826 | BN_free(prime); | |
2827 | return prime_len; | |
2828 | #endif | |
2829 | } | |
2830 | ||
2831 | ||
2832 | struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, | |
2833 | const u8 *data, size_t len) | |
2834 | { | |
2785 | 2835 | ECDSA_SIG *sig = NULL; |
2786 | 2836 | const BIGNUM *r, *s; |
2787 | 2837 | u8 *r_buf, *s_buf; |
2789 | 2839 | const unsigned char *p; |
2790 | 2840 | int prime_len; |
2791 | 2841 | |
2842 | prime_len = openssl_evp_pkey_ec_prime_len(key); | |
2843 | if (prime_len < 0) | |
2844 | return NULL; | |
2845 | ||
2792 | 2846 | buf = crypto_ec_key_sign(key, data, len); |
2793 | 2847 | if (!buf) |
2794 | 2848 | return NULL; |
2795 | 2849 | |
2796 | 2850 | /* Extract (r,s) from Ecdsa-Sig-Value */ |
2797 | eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); | |
2798 | if (!eckey) | |
2799 | goto fail; | |
2800 | group = EC_KEY_get0_group(eckey); | |
2801 | prime = BN_new(); | |
2802 | if (!prime || !group || | |
2803 | !EC_GROUP_get_curve_GFp(group, prime, NULL, NULL, NULL)) | |
2804 | goto fail; | |
2805 | prime_len = BN_num_bytes(prime); | |
2806 | 2851 | |
2807 | 2852 | p = wpabuf_head(buf); |
2808 | 2853 | sig = d2i_ECDSA_SIG(NULL, &p, wpabuf_len(buf)); |
2821 | 2866 | goto fail; |
2822 | 2867 | |
2823 | 2868 | out: |
2824 | BN_free(prime); | |
2825 | 2869 | ECDSA_SIG_free(sig); |
2826 | 2870 | return buf; |
2827 | 2871 | fail: |
2892 | 2936 | |
2893 | 2937 | int crypto_ec_key_group(struct crypto_ec_key *key) |
2894 | 2938 | { |
2939 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L | |
2940 | char gname[50]; | |
2941 | int nid; | |
2942 | ||
2943 | if (EVP_PKEY_get_group_name((EVP_PKEY *) key, gname, sizeof(gname), | |
2944 | NULL) != 1) | |
2945 | return -1; | |
2946 | nid = OBJ_txt2nid(gname); | |
2947 | #else | |
2895 | 2948 | const EC_KEY *eckey; |
2896 | 2949 | const EC_GROUP *group; |
2897 | 2950 | int nid; |
2903 | 2956 | if (!group) |
2904 | 2957 | return -1; |
2905 | 2958 | nid = EC_GROUP_get_curve_name(group); |
2959 | #endif | |
2906 | 2960 | switch (nid) { |
2907 | 2961 | case NID_X9_62_prime256v1: |
2908 | 2962 | return 19; |
2931 | 2985 | |
2932 | 2986 | int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2) |
2933 | 2987 | { |
2988 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L | |
2989 | if (EVP_PKEY_eq((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1) | |
2990 | return -1; | |
2991 | #else | |
2934 | 2992 | if (EVP_PKEY_cmp((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1) |
2935 | 2993 | return -1; |
2994 | #endif | |
2936 | 2995 | return 0; |
2937 | 2996 | } |
2938 | 2997 |
49 | 49 | for (j = 0; j < SHA1_MAC_LEN; j++) |
50 | 50 | digest[j] ^= tmp2[j]; |
51 | 51 | } |
52 | forced_memzero(tmp, SHA1_MAC_LEN); | |
53 | forced_memzero(tmp2, SHA1_MAC_LEN); | |
52 | 54 | |
53 | 55 | return 0; |
54 | 56 | } |
86 | 88 | pos += plen; |
87 | 89 | left -= plen; |
88 | 90 | } |
91 | forced_memzero(digest, SHA1_MAC_LEN); | |
89 | 92 | |
90 | 93 | return 0; |
91 | 94 | } |
2528 | 2528 | #ifdef CONFIG_SUITEB |
2529 | 2529 | if (conn->flags & TLS_CONN_SUITEB) { |
2530 | 2530 | EVP_PKEY *pk; |
2531 | RSA *rsa; | |
2532 | 2531 | int len = -1; |
2533 | 2532 | |
2534 | 2533 | pk = X509_get_pubkey(err_cert); |
2535 | 2534 | if (pk) { |
2536 | rsa = EVP_PKEY_get1_RSA(pk); | |
2537 | if (rsa) { | |
2538 | len = RSA_bits(rsa); | |
2539 | RSA_free(rsa); | |
2540 | } | |
2535 | len = EVP_PKEY_bits(pk); | |
2541 | 2536 | EVP_PKEY_free(pk); |
2542 | 2537 | } |
2543 | 2538 | |
3063 | 3058 | return -1; |
3064 | 3059 | } |
3065 | 3060 | } else if (flags & TLS_CONN_SUITEB) { |
3061 | #if OPENSSL_VERSION_NUMBER < 0x30000000L | |
3066 | 3062 | EC_KEY *ecdh; |
3063 | #endif | |
3067 | 3064 | const char *ciphers = |
3068 | 3065 | "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384"; |
3069 | 3066 | int nid[1] = { NID_secp384r1 }; |
3080 | 3077 | return -1; |
3081 | 3078 | } |
3082 | 3079 | |
3080 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L | |
3081 | if (SSL_set1_groups(ssl, nid, 1) != 1) { | |
3082 | wpa_printf(MSG_INFO, | |
3083 | "OpenSSL: Failed to set Suite B groups"); | |
3084 | return -1; | |
3085 | } | |
3086 | ||
3087 | #else | |
3083 | 3088 | if (SSL_set1_curves(ssl, nid, 1) != 1) { |
3084 | 3089 | wpa_printf(MSG_INFO, |
3085 | 3090 | "OpenSSL: Failed to set Suite B curves"); |
3094 | 3099 | return -1; |
3095 | 3100 | } |
3096 | 3101 | EC_KEY_free(ecdh); |
3102 | #endif | |
3097 | 3103 | } |
3098 | 3104 | if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) { |
3099 | 3105 | #ifdef OPENSSL_IS_BORINGSSL |
781 | 781 | * for IEEE 802.11ay EDMG configuration. |
782 | 782 | */ |
783 | 783 | struct ieee80211_edmg_config edmg; |
784 | ||
785 | /** | |
786 | * radar_background - Whether radar/CAC background is requested | |
787 | */ | |
788 | bool radar_background; | |
784 | 789 | }; |
785 | 790 | |
786 | 791 | /** |
1035 | 1040 | * |
1036 | 1041 | * If the driver needs to do special configuration for WPS association, |
1037 | 1042 | * this variable provides more information on what type of association |
1038 | * is being requested. Most drivers should not need ot use this. | |
1043 | * is being requested. Most drivers should not need to use this. | |
1039 | 1044 | */ |
1040 | 1045 | enum wps_mode wps; |
1041 | 1046 | |
1774 | 1779 | WPA_IF_P2P_GROUP, |
1775 | 1780 | |
1776 | 1781 | /** |
1777 | * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the | |
1782 | * WPA_IF_P2P_DEVICE - P2P Device interface is used to identify the | |
1778 | 1783 | * abstracted P2P Device function in the driver |
1779 | 1784 | */ |
1780 | 1785 | WPA_IF_P2P_DEVICE, |
2026 | 2031 | #define WPA_DRIVER_FLAGS2_OCV 0x0000000000000080ULL |
2027 | 2032 | /** Driver expects user space implementation of SME in AP mode */ |
2028 | 2033 | #define WPA_DRIVER_FLAGS2_AP_SME 0x0000000000000100ULL |
2034 | /** Driver handles SA Query procedures in AP mode */ | |
2035 | #define WPA_DRIVER_FLAGS2_SA_QUERY_OFFLOAD_AP 0x0000000000000200ULL | |
2036 | /** Driver supports background radar/CAC detection */ | |
2037 | #define WPA_DRIVER_RADAR_BACKGROUND 0x0000000000000400ULL | |
2029 | 2038 | u64 flags2; |
2030 | 2039 | |
2031 | 2040 | #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ |
2598 | 2607 | * some drivers may expect them in different order than wpa_supplicant |
2599 | 2608 | * is using. If the TX/RX keys are swapped, all TKIP encrypted packets |
2600 | 2609 | * will trigger Michael MIC errors. This can be fixed by changing the |
2601 | * order of MIC keys by swapping te bytes 16..23 and 24..31 of the key | |
2610 | * order of MIC keys by swapping the bytes 16..23 and 24..31 of the key | |
2602 | 2611 | * in driver_*.c set_key() implementation, see driver_ndis.c for an |
2603 | 2612 | * example on how this can be done. |
2604 | 2613 | */ |
4607 | 4616 | * This event must be delivered when a Michael MIC error is detected by |
4608 | 4617 | * the local driver. Additional data for event processing is |
4609 | 4618 | * provided with union wpa_event_data::michael_mic_failure. This |
4610 | * information is used to request new encyption key and to initiate | |
4619 | * information is used to request new encryption key and to initiate | |
4611 | 4620 | * TKIP countermeasures if needed. |
4612 | 4621 | */ |
4613 | 4622 | EVENT_MICHAEL_MIC_FAILURE, |
5128 | 5137 | * is required to provide more details of the frame. |
5129 | 5138 | */ |
5130 | 5139 | EVENT_UNPROT_BEACON, |
5140 | ||
5141 | /** | |
5142 | * EVENT_TX_WAIT_EXPIRE - TX wait timed out | |
5143 | * | |
5144 | * This event is used to indicate when the driver has completed | |
5145 | * wait for a response frame based on a TX request that specified a | |
5146 | * non-zero wait time and that has not been explicitly cancelled. | |
5147 | */ | |
5148 | EVENT_TX_WAIT_EXPIRE, | |
5131 | 5149 | }; |
5132 | 5150 | |
5133 | 5151 |
16 | 16 | #include "eloop.h" |
17 | 17 | #include "common/ieee802_11_defs.h" |
18 | 18 | #include "l2_packet/l2_packet.h" |
19 | #include "p2p/p2p.h" | |
20 | 19 | |
21 | 20 | #include "common.h" |
22 | 21 | #ifndef _BYTE_ORDER |
89 | 89 | E2S(WDS_STA_INTERFACE_STATUS); |
90 | 90 | E2S(UPDATE_DH); |
91 | 91 | E2S(UNPROT_BEACON); |
92 | E2S(TX_WAIT_EXPIRE); | |
92 | 93 | } |
93 | 94 | |
94 | 95 | return "UNKNOWN"; |
76 | 76 | |
77 | 77 | u8 encoding_sa; |
78 | 78 | bool encoding_sa_set; |
79 | ||
80 | u64 cipher_suite; | |
81 | bool cipher_suite_set; | |
79 | 82 | }; |
80 | 83 | |
81 | 84 | |
459 | 462 | */ |
460 | 463 | static int macsec_drv_set_current_cipher_suite(void *priv, u64 cs) |
461 | 464 | { |
465 | struct macsec_drv_data *drv = priv; | |
466 | ||
462 | 467 | wpa_printf(MSG_DEBUG, "%s -> %016" PRIx64, __func__, cs); |
463 | return 0; | |
468 | ||
469 | drv->cipher_suite_set = true; | |
470 | drv->cipher_suite = cs; | |
471 | ||
472 | return try_commit(drv); | |
464 | 473 | } |
465 | 474 | |
466 | 475 | |
1062 | 1071 | } |
1063 | 1072 | |
1064 | 1073 | |
1065 | static struct rtnl_link * lookup_sc(struct nl_cache *cache, int parent, u64 sci) | |
1074 | static struct rtnl_link * lookup_sc(struct nl_cache *cache, int parent, u64 sci, | |
1075 | u64 cs) | |
1066 | 1076 | { |
1067 | 1077 | struct rtnl_link *needle; |
1068 | 1078 | void *match; |
1073 | 1083 | |
1074 | 1084 | rtnl_link_set_link(needle, parent); |
1075 | 1085 | rtnl_link_macsec_set_sci(needle, sci); |
1086 | if (cs) | |
1087 | rtnl_link_macsec_set_cipher_suite(needle, cs); | |
1076 | 1088 | |
1077 | 1089 | match = nl_cache_find(cache, (struct nl_object *) needle); |
1078 | 1090 | rtnl_link_put(needle); |
1097 | 1109 | char *ifname; |
1098 | 1110 | u64 sci; |
1099 | 1111 | int err; |
1112 | u64 cs = 0; | |
1100 | 1113 | |
1101 | 1114 | wpa_printf(MSG_DEBUG, DRV_PREFIX |
1102 | 1115 | "%s: create_transmit_sc -> " SCISTR " (conf_offset=%d)", |
1120 | 1133 | rtnl_link_macsec_set_sci(link, sci); |
1121 | 1134 | |
1122 | 1135 | drv->created_link = true; |
1136 | ||
1137 | if (drv->cipher_suite_set) { | |
1138 | cs = drv->cipher_suite; | |
1139 | drv->cipher_suite_set = false; | |
1140 | rtnl_link_macsec_set_cipher_suite(link, cs); | |
1141 | } | |
1123 | 1142 | |
1124 | 1143 | err = rtnl_link_add(drv->sk, link, NLM_F_CREATE); |
1125 | 1144 | if (err == -NLE_BUSY) { |
1136 | 1155 | rtnl_link_put(link); |
1137 | 1156 | |
1138 | 1157 | nl_cache_refill(drv->sk, drv->link_cache); |
1139 | link = lookup_sc(drv->link_cache, drv->parent_ifi, sci); | |
1158 | link = lookup_sc(drv->link_cache, drv->parent_ifi, sci, cs); | |
1140 | 1159 | if (!link) { |
1141 | 1160 | wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't find link"); |
1142 | 1161 | return -1; |
860 | 860 | } |
861 | 861 | } |
862 | 862 | |
863 | wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__); | |
863 | wpa_printf(MSG_DEBUG, "%s: no available channel", __func__); | |
864 | 864 | |
865 | 865 | return -1; |
866 | 866 | } |
2935 | 2935 | |
2936 | 2936 | wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)", |
2937 | 2937 | drv->ifindex); |
2938 | bss->beacon_set = 0; | |
2939 | bss->freq = 0; | |
2938 | 2940 | nl80211_put_wiphy_data_ap(bss); |
2939 | 2941 | msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON); |
2940 | 2942 | return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); |
4655 | 4657 | nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) |
4656 | 4658 | goto fail; |
4657 | 4659 | |
4658 | if (drv->device_ap_sme && | |
4659 | (params->key_mgmt_suites & WPA_KEY_MGMT_SAE) && | |
4660 | nla_put_flag(msg, NL80211_ATTR_EXTERNAL_AUTH_SUPPORT)) | |
4661 | goto fail; | |
4660 | if (drv->device_ap_sme) { | |
4661 | u32 flags = 0; | |
4662 | ||
4663 | if (params->key_mgmt_suites & WPA_KEY_MGMT_SAE) { | |
4664 | /* Add the previously used flag attribute to support | |
4665 | * older kernel versions and the newer flag bit for | |
4666 | * newer kernels. */ | |
4667 | if (nla_put_flag(msg, | |
4668 | NL80211_ATTR_EXTERNAL_AUTH_SUPPORT)) | |
4669 | goto fail; | |
4670 | flags |= NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT; | |
4671 | } | |
4672 | ||
4673 | flags |= NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT; | |
4674 | ||
4675 | if (nla_put_u32(msg, NL80211_ATTR_AP_SETTINGS_FLAGS, flags)) | |
4676 | goto fail; | |
4677 | } | |
4662 | 4678 | |
4663 | 4679 | wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x", |
4664 | 4680 | params->pairwise_ciphers); |
4895 | 4911 | wpa_printf(MSG_DEBUG, " * he_enabled=%d", freq->he_enabled); |
4896 | 4912 | wpa_printf(MSG_DEBUG, " * vht_enabled=%d", freq->vht_enabled); |
4897 | 4913 | wpa_printf(MSG_DEBUG, " * ht_enabled=%d", freq->ht_enabled); |
4914 | wpa_printf(MSG_DEBUG, " * radar_background=%d", | |
4915 | freq->radar_background); | |
4898 | 4916 | |
4899 | 4917 | hw_mode = ieee80211_freq_to_chan(freq->freq, &channel); |
4900 | 4918 | is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G || |
4972 | 4990 | NL80211_CHAN_NO_HT)) |
4973 | 4991 | return -ENOBUFS; |
4974 | 4992 | } |
4993 | if (freq->radar_background) | |
4994 | nla_put_flag(msg, NL80211_ATTR_RADAR_BACKGROUND); | |
4995 | ||
4975 | 4996 | return 0; |
4976 | 4997 | } |
4977 | 4998 | |
8149 | 8170 | if (save_cookie) |
8150 | 8171 | drv->send_frame_cookie = no_ack ? (u64) -1 : cookie; |
8151 | 8172 | |
8173 | if (!wait) { | |
8174 | /* There is no need to store this cookie since there | |
8175 | * is no wait that could be canceled later. */ | |
8176 | goto fail; | |
8177 | } | |
8152 | 8178 | if (drv->num_send_frame_cookies == MAX_SEND_FRAME_COOKIES) { |
8153 | 8179 | wpa_printf(MSG_DEBUG, |
8154 | 8180 | "nl80211: Drop oldest pending send frame cookie 0x%llx", |
8279 | 8305 | u64 cookie; |
8280 | 8306 | |
8281 | 8307 | /* Cancel the last pending TX cookie */ |
8282 | nl80211_frame_wait_cancel(bss, drv->send_frame_cookie); | |
8308 | if (drv->send_frame_cookie != (u64) -1) | |
8309 | nl80211_frame_wait_cancel(bss, drv->send_frame_cookie); | |
8283 | 8310 | |
8284 | 8311 | /* |
8285 | 8312 | * Cancel the other pending TX cookies, if any. This is needed since |
8471 | 8498 | if (!is_ap_interface(drv->nlmode)) |
8472 | 8499 | return -1; |
8473 | 8500 | wpa_driver_nl80211_del_beacon(bss); |
8474 | bss->beacon_set = 0; | |
8475 | 8501 | |
8476 | 8502 | /* |
8477 | 8503 | * If the P2P GO interface was dynamically added, then it is |
8491 | 8517 | if (!is_ap_interface(drv->nlmode)) |
8492 | 8518 | return -1; |
8493 | 8519 | wpa_driver_nl80211_del_beacon(bss); |
8494 | bss->beacon_set = 0; | |
8495 | 8520 | return 0; |
8496 | 8521 | } |
8497 | 8522 | |
10625 | 10650 | } else { |
10626 | 10651 | wpa_printf(MSG_DEBUG, |
10627 | 10652 | "nl80211: mesh leave request send successfully"); |
10653 | drv->first_bss->freq = 0; | |
10628 | 10654 | } |
10629 | 10655 | |
10630 | 10656 | if (drv->start_mode_sta && |
12094 | 12120 | |
12095 | 12121 | |
12096 | 12122 | #ifdef CONFIG_TESTING_OPTIONS |
12123 | ||
12097 | 12124 | static int testing_nl80211_register_frame(void *priv, u16 type, |
12098 | 12125 | const u8 *match, size_t match_len, |
12099 | 12126 | bool multicast) |
12107 | 12134 | return nl80211_register_frame(bss, handle, type, match, match_len, |
12108 | 12135 | multicast); |
12109 | 12136 | } |
12137 | ||
12138 | ||
12139 | static int testing_nl80211_radio_disable(void *priv, int disabled) | |
12140 | { | |
12141 | struct i802_bss *bss = priv; | |
12142 | struct wpa_driver_nl80211_data *drv = bss->drv; | |
12143 | ||
12144 | /* For now, this is supported only partially in station mode with | |
12145 | * SME-in-wpa_supplicant case where the NL80211_ATTR_LOCAL_STATE_CHANGE | |
12146 | * attribute can be used to avoid sending out the Deauthentication frame | |
12147 | * to the currently associated AP. */ | |
12148 | ||
12149 | if (!disabled) | |
12150 | return 0; | |
12151 | ||
12152 | if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) | |
12153 | return -1; | |
12154 | ||
12155 | if (!drv->associated) | |
12156 | return 0; | |
12157 | ||
12158 | return wpa_driver_nl80211_mlme(drv, drv->bssid, | |
12159 | NL80211_CMD_DEAUTHENTICATE, | |
12160 | WLAN_REASON_PREV_AUTH_NOT_VALID, 1, | |
12161 | drv->first_bss); | |
12162 | } | |
12163 | ||
12110 | 12164 | #endif /* CONFIG_TESTING_OPTIONS */ |
12111 | 12165 | |
12112 | 12166 | |
12250 | 12304 | #endif /* CONFIG_DPP */ |
12251 | 12305 | #ifdef CONFIG_TESTING_OPTIONS |
12252 | 12306 | .register_frame = testing_nl80211_register_frame, |
12307 | .radio_disable = testing_nl80211_radio_disable, | |
12253 | 12308 | #endif /* CONFIG_TESTING_OPTIONS */ |
12254 | 12309 | }; |
664 | 664 | if (ext_feature_isset(ext_features, len, |
665 | 665 | NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION)) |
666 | 666 | capa->flags2 |= WPA_DRIVER_FLAGS2_OCV; |
667 | ||
668 | if (ext_feature_isset(ext_features, len, | |
669 | NL80211_EXT_FEATURE_RADAR_BACKGROUND)) | |
670 | capa->flags2 |= WPA_DRIVER_RADAR_BACKGROUND; | |
667 | 671 | } |
668 | 672 | |
669 | 673 | |
919 | 923 | wiphy_info_tdls(capa, tb[NL80211_ATTR_TDLS_SUPPORT], |
920 | 924 | tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]); |
921 | 925 | |
922 | if (tb[NL80211_ATTR_DEVICE_AP_SME]) | |
926 | if (tb[NL80211_ATTR_DEVICE_AP_SME]) { | |
927 | u32 ap_sme_features_flags = | |
928 | nla_get_u32(tb[NL80211_ATTR_DEVICE_AP_SME]); | |
929 | ||
930 | if (ap_sme_features_flags & NL80211_AP_SME_SA_QUERY_OFFLOAD) | |
931 | capa->flags2 |= WPA_DRIVER_FLAGS2_SA_QUERY_OFFLOAD_AP; | |
932 | ||
923 | 933 | info->device_ap_sme = 1; |
934 | } | |
924 | 935 | |
925 | 936 | wiphy_info_feature_flags(info, tb[NL80211_ATTR_FEATURE_FLAGS]); |
926 | 937 | wiphy_info_ext_feature_flags(info, tb[NL80211_ATTR_EXT_FEATURES]); |
1329 | 1340 | drv->has_capability = 1; |
1330 | 1341 | drv->has_driver_key_mgmt = info.has_key_mgmt | info.has_key_mgmt_iftype; |
1331 | 1342 | |
1332 | /* Fallback to hardcoded defaults if the driver does nott advertize any | |
1343 | /* Fallback to hardcoded defaults if the driver does not advertise any | |
1333 | 1344 | * AKM capabilities. */ |
1334 | 1345 | if (!drv->has_driver_key_mgmt) { |
1335 | 1346 | drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | |
171 | 171 | C2S(NL80211_CMD_UNPROT_BEACON) |
172 | 172 | C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS) |
173 | 173 | C2S(NL80211_CMD_SET_SAR_SPECS) |
174 | C2S(NL80211_CMD_OBSS_COLOR_COLLISION) | |
175 | C2S(NL80211_CMD_COLOR_CHANGE_REQUEST) | |
176 | C2S(NL80211_CMD_COLOR_CHANGE_STARTED) | |
177 | C2S(NL80211_CMD_COLOR_CHANGE_ABORTED) | |
178 | C2S(NL80211_CMD_COLOR_CHANGE_COMPLETED) | |
179 | C2S(NL80211_CMD_SET_FILS_AAD) | |
180 | C2S(NL80211_CMD_ASSOC_COMEBACK) | |
174 | 181 | C2S(__NL80211_CMD_AFTER_LAST) |
175 | 182 | } |
176 | 183 | #undef C2S |
2823 | 2830 | nla_len(tb[NL80211_ATTR_FRAME])); |
2824 | 2831 | break; |
2825 | 2832 | default: |
2826 | wpa_printf(MSG_INFO, "nl80211: Unxpected ethertype 0x%04x from " | |
2833 | wpa_printf(MSG_INFO, | |
2834 | "nl80211: Unexpected ethertype 0x%04x from " | |
2827 | 2835 | MACSTR " over control port", |
2828 | 2836 | ethertype, MAC2STR(src_addr)); |
2829 | 2837 | break; |
2851 | 2859 | event.eapol_tx_status.data_len = len - ETH_HLEN; |
2852 | 2860 | event.eapol_tx_status.ack = ack != NULL; |
2853 | 2861 | wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); |
2862 | } | |
2863 | ||
2864 | ||
2865 | static void nl80211_frame_wait_cancel(struct wpa_driver_nl80211_data *drv, | |
2866 | struct nlattr *cookie_attr) | |
2867 | { | |
2868 | unsigned int i; | |
2869 | u64 cookie; | |
2870 | bool match = false; | |
2871 | ||
2872 | if (!cookie_attr) | |
2873 | return; | |
2874 | cookie = nla_get_u64(cookie_attr); | |
2875 | ||
2876 | for (i = 0; i < drv->num_send_frame_cookies; i++) { | |
2877 | if (cookie == drv->send_frame_cookies[i]) { | |
2878 | match = true; | |
2879 | break; | |
2880 | } | |
2881 | } | |
2882 | wpa_printf(MSG_DEBUG, | |
2883 | "nl80211: TX frame wait expired for cookie 0x%llx%s%s", | |
2884 | (long long unsigned int) cookie, | |
2885 | match ? " (match)" : "", | |
2886 | drv->send_frame_cookie == cookie ? " (match-saved)" : ""); | |
2887 | if (drv->send_frame_cookie == cookie) | |
2888 | drv->send_frame_cookie = (u64) -1; | |
2889 | if (!match) | |
2890 | return; | |
2891 | ||
2892 | if (i < drv->num_send_frame_cookies - 1) | |
2893 | os_memmove(&drv->send_frame_cookies[i], | |
2894 | &drv->send_frame_cookies[i + 1], | |
2895 | (drv->num_send_frame_cookies - i - 1) * sizeof(u64)); | |
2896 | drv->num_send_frame_cookies--; | |
2897 | ||
2898 | wpa_supplicant_event(drv->ctx, EVENT_TX_WAIT_EXPIRE, NULL); | |
2899 | } | |
2900 | ||
2901 | ||
2902 | static void nl80211_assoc_comeback(struct wpa_driver_nl80211_data *drv, | |
2903 | struct nlattr *mac, struct nlattr *timeout) | |
2904 | { | |
2905 | if (!mac || !timeout) | |
2906 | return; | |
2907 | wpa_printf(MSG_DEBUG, "nl80211: Association comeback requested by " | |
2908 | MACSTR " (timeout: %u ms)", | |
2909 | MAC2STR((u8 *) nla_data(mac)), nla_get_u32(timeout)); | |
2854 | 2910 | } |
2855 | 2911 | |
2856 | 2912 | |
3100 | 3156 | tb[NL80211_ATTR_ACK], |
3101 | 3157 | tb[NL80211_ATTR_COOKIE]); |
3102 | 3158 | break; |
3159 | case NL80211_CMD_FRAME_WAIT_CANCEL: | |
3160 | nl80211_frame_wait_cancel(drv, tb[NL80211_ATTR_COOKIE]); | |
3161 | break; | |
3162 | case NL80211_CMD_ASSOC_COMEBACK: | |
3163 | nl80211_assoc_comeback(drv, tb[NL80211_ATTR_MAC], | |
3164 | tb[NL80211_ATTR_TIMEOUT]); | |
3165 | break; | |
3103 | 3166 | default: |
3104 | 3167 | wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " |
3105 | 3168 | "(cmd=%d)", cmd); |
371 | 371 | L"MSNdis_NotifyAdapterRemoval") == 0) { |
372 | 372 | ndis_events_adapter_removal(events); |
373 | 373 | } else { |
374 | wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: " | |
375 | "'%S'", vtClass.bstrVal); | |
374 | wpa_printf(MSG_DEBUG, | |
375 | "Unexpected event - __CLASS: '%S'", | |
376 | vtClass.bstrVal); | |
376 | 377 | } |
377 | 378 | |
378 | 379 | VariantClear(&vtClass); |
10 | 10 | * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> |
11 | 11 | * Copyright 2008 Colin McCabe <colin@cozybit.com> |
12 | 12 | * Copyright 2015-2017 Intel Deutschland GmbH |
13 | * Copyright (C) 2018-2020 Intel Corporation | |
13 | * Copyright (C) 2018-2022 Intel Corporation | |
14 | 14 | * |
15 | 15 | * Permission to use, copy, modify, and/or distribute this software for any |
16 | 16 | * purpose with or without fee is hereby granted, provided that the above |
297 | 297 | * i.e. the configuration will be reset to default when the STA connects back |
298 | 298 | * after disconnection/roaming, and this configuration will be cleared when |
299 | 299 | * the interface goes down. |
300 | */ | |
301 | ||
302 | /** | |
303 | * DOC: FILS shared key crypto offload | |
304 | * | |
305 | * This feature is applicable to drivers running in AP mode. | |
306 | * | |
307 | * FILS shared key crypto offload can be advertised by drivers by setting | |
308 | * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD flag. The drivers that support | |
309 | * FILS shared key crypto offload should be able to encrypt and decrypt | |
310 | * association frames for FILS shared key authentication as per IEEE 802.11ai. | |
311 | * With this capability, for FILS key derivation, drivers depend on userspace. | |
312 | * | |
313 | * After FILS key derivation, userspace shares the FILS AAD details with the | |
314 | * driver and the driver stores the same to use in decryption of association | |
315 | * request and in encryption of association response. The below parameters | |
316 | * should be given to the driver in %NL80211_CMD_SET_FILS_AAD. | |
317 | * %NL80211_ATTR_MAC - STA MAC address, used for storing FILS AAD per STA | |
318 | * %NL80211_ATTR_FILS_KEK - Used for encryption or decryption | |
319 | * %NL80211_ATTR_FILS_NONCES - Used for encryption or decryption | |
320 | * (STA Nonce 16 bytes followed by AP Nonce 16 bytes) | |
321 | * | |
322 | * Once the association is done, the driver cleans the FILS AAD data. | |
300 | 323 | */ |
301 | 324 | |
302 | 325 | /** |
336 | 359 | * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes |
337 | 360 | * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from |
338 | 361 | * userspace to request deletion of a virtual interface, then requires |
339 | * attribute %NL80211_ATTR_IFINDEX. | |
362 | * attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are | |
363 | * enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS, | |
364 | * and if this command is used for the transmitting interface, then all | |
365 | * the non-transmitting interfaces are deleted as well. | |
340 | 366 | * |
341 | 367 | * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified |
342 | 368 | * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. |
1184 | 1210 | * passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to |
1185 | 1211 | * specify the wiphy index to be applied to. |
1186 | 1212 | * |
1213 | * @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever | |
1214 | * mac80211/drv detects a bss color collision. | |
1215 | * | |
1216 | * @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that | |
1217 | * userspace wants to change the BSS color. | |
1218 | * | |
1219 | * @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has | |
1220 | * started | |
1221 | * | |
1222 | * @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has | |
1223 | * been aborted | |
1224 | * | |
1225 | * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change | |
1226 | * has completed | |
1227 | * | |
1228 | * @NL80211_CMD_SET_FILS_AAD: Set FILS AAD data to the driver using - | |
1229 | * &NL80211_ATTR_MAC - for STA MAC address | |
1230 | * &NL80211_ATTR_FILS_KEK - for KEK | |
1231 | * &NL80211_ATTR_FILS_NONCES - for FILS Nonces | |
1232 | * (STA Nonce 16 bytes followed by AP Nonce 16 bytes) | |
1233 | * | |
1234 | * @NL80211_CMD_ASSOC_COMEBACK: notification about an association | |
1235 | * temporal rejection with comeback. The event includes %NL80211_ATTR_MAC | |
1236 | * to describe the BSSID address of the AP and %NL80211_ATTR_TIMEOUT to | |
1237 | * specify the timeout value. | |
1238 | * | |
1187 | 1239 | * @NL80211_CMD_MAX: highest used command number |
1188 | 1240 | * @__NL80211_CMD_AFTER_LAST: internal use |
1189 | 1241 | */ |
1415 | 1467 | NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS, |
1416 | 1468 | |
1417 | 1469 | NL80211_CMD_SET_SAR_SPECS, |
1470 | ||
1471 | NL80211_CMD_OBSS_COLOR_COLLISION, | |
1472 | ||
1473 | NL80211_CMD_COLOR_CHANGE_REQUEST, | |
1474 | ||
1475 | NL80211_CMD_COLOR_CHANGE_STARTED, | |
1476 | NL80211_CMD_COLOR_CHANGE_ABORTED, | |
1477 | NL80211_CMD_COLOR_CHANGE_COMPLETED, | |
1478 | ||
1479 | NL80211_CMD_SET_FILS_AAD, | |
1480 | ||
1481 | NL80211_CMD_ASSOC_COMEBACK, | |
1418 | 1482 | |
1419 | 1483 | /* add new commands above here */ |
1420 | 1484 | |
2412 | 2476 | * space supports external authentication. This attribute shall be used |
2413 | 2477 | * with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver |
2414 | 2478 | * may offload authentication processing to user space if this capability |
2415 | * is indicated in the respective requests from the user space. | |
2479 | * is indicated in the respective requests from the user space. (This flag | |
2480 | * attribute deprecated for %NL80211_CMD_START_AP, use | |
2481 | * %NL80211_ATTR_AP_SETTINGS_FLAGS) | |
2416 | 2482 | * |
2417 | 2483 | * @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this |
2418 | 2484 | * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED. |
2559 | 2625 | * disassoc events to indicate that an immediate reconnect to the AP |
2560 | 2626 | * is desired. |
2561 | 2627 | * |
2628 | * @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the | |
2629 | * %NL80211_CMD_OBSS_COLOR_COLLISION event. | |
2630 | * | |
2631 | * @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's | |
2632 | * until the color switch event. | |
2633 | * @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are | |
2634 | * switching to | |
2635 | * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE | |
2636 | * information for the time while performing a color switch. | |
2637 | * | |
2638 | * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID | |
2639 | * advertisements (MBSSID) parameters in AP mode. | |
2640 | * Kernel uses this attribute to indicate the driver's support for MBSSID | |
2641 | * and enhanced multi-BSSID advertisements (EMA AP) to the userspace. | |
2642 | * Userspace should use this attribute to configure per interface MBSSID | |
2643 | * parameters. | |
2644 | * See &enum nl80211_mbssid_config_attributes for details. | |
2645 | * | |
2646 | * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements. | |
2647 | * Mandatory parameter for the transmitting interface to enable MBSSID. | |
2648 | * Optional for the non-transmitting interfaces. | |
2649 | * | |
2650 | * @NL80211_ATTR_RADAR_BACKGROUND: Configure dedicated offchannel chain | |
2651 | * available for radar/CAC detection on some hw. This chain can't be used | |
2652 | * to transmit or receive frames and it is bounded to a running wdev. | |
2653 | * Background radar/CAC detection allows to avoid the CAC downtime | |
2654 | * switching on a different channel during CAC detection on the selected | |
2655 | * radar channel. | |
2656 | * | |
2657 | * @NL80211_ATTR_AP_SETTINGS_FLAGS: u32 attribute contains ap settings flags, | |
2658 | * enumerated in &enum nl80211_ap_settings_flags. This attribute shall be | |
2659 | * used with %NL80211_CMD_START_AP request. | |
2660 | * | |
2661 | * @NL80211_ATTR_EHT_CAPABILITY: EHT Capability information element (from | |
2662 | * association request when used with NL80211_CMD_NEW_STATION). Can be set | |
2663 | * only if %NL80211_STA_FLAG_WME is set. | |
2664 | * | |
2562 | 2665 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
2563 | 2666 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
2564 | 2667 | * @__NL80211_ATTR_AFTER_LAST: internal use |
3055 | 3158 | NL80211_ATTR_SAR_SPEC, |
3056 | 3159 | |
3057 | 3160 | NL80211_ATTR_DISABLE_HE, |
3161 | ||
3162 | NL80211_ATTR_OBSS_COLOR_BITMAP, | |
3163 | ||
3164 | NL80211_ATTR_COLOR_CHANGE_COUNT, | |
3165 | NL80211_ATTR_COLOR_CHANGE_COLOR, | |
3166 | NL80211_ATTR_COLOR_CHANGE_ELEMS, | |
3167 | ||
3168 | NL80211_ATTR_MBSSID_CONFIG, | |
3169 | NL80211_ATTR_MBSSID_ELEMS, | |
3170 | ||
3171 | NL80211_ATTR_RADAR_BACKGROUND, | |
3172 | ||
3173 | NL80211_ATTR_AP_SETTINGS_FLAGS, | |
3174 | ||
3175 | NL80211_ATTR_EHT_CAPABILITY, | |
3058 | 3176 | |
3059 | 3177 | /* add attributes here, update the policy in nl80211.c */ |
3060 | 3178 | |
3111 | 3229 | #define NL80211_HE_MAX_CAPABILITY_LEN 54 |
3112 | 3230 | #define NL80211_MAX_NR_CIPHER_SUITES 5 |
3113 | 3231 | #define NL80211_MAX_NR_AKM_SUITES 2 |
3232 | #define NL80211_EHT_MIN_CAPABILITY_LEN 13 | |
3233 | #define NL80211_EHT_MAX_CAPABILITY_LEN 51 | |
3114 | 3234 | |
3115 | 3235 | #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 |
3116 | 3236 | |
3138 | 3258 | * and therefore can't be created in the normal ways, use the |
3139 | 3259 | * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE |
3140 | 3260 | * commands to create and destroy one |
3141 | * @NL80211_IF_TYPE_OCB: Outside Context of a BSS | |
3261 | * @NL80211_IFTYPE_OCB: Outside Context of a BSS | |
3142 | 3262 | * This mode corresponds to the MIB variable dot11OCBActivated=true |
3143 | 3263 | * @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev) |
3144 | 3264 | * @NL80211_IFTYPE_MAX: highest interface type number currently defined |
3277 | 3397 | NL80211_RATE_INFO_HE_RU_ALLOC_484, |
3278 | 3398 | NL80211_RATE_INFO_HE_RU_ALLOC_996, |
3279 | 3399 | NL80211_RATE_INFO_HE_RU_ALLOC_2x996, |
3400 | }; | |
3401 | ||
3402 | /** | |
3403 | * enum nl80211_eht_gi - EHT guard interval | |
3404 | * @NL80211_RATE_INFO_EHT_GI_0_8: 0.8 usec | |
3405 | * @NL80211_RATE_INFO_EHT_GI_1_6: 1.6 usec | |
3406 | * @NL80211_RATE_INFO_EHT_GI_3_2: 3.2 usec | |
3407 | */ | |
3408 | enum nl80211_eht_gi { | |
3409 | NL80211_RATE_INFO_EHT_GI_0_8, | |
3410 | NL80211_RATE_INFO_EHT_GI_1_6, | |
3411 | NL80211_RATE_INFO_EHT_GI_3_2, | |
3412 | }; | |
3413 | ||
3414 | /** | |
3415 | * enum nl80211_eht_ru_alloc - EHT RU allocation values | |
3416 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_26: 26-tone RU allocation | |
3417 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_52: 52-tone RU allocation | |
3418 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_52P26: 52+26-tone RU allocation | |
3419 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_106: 106-tone RU allocation | |
3420 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_106P26: 106+26 tone RU allocation | |
3421 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_242: 242-tone RU allocation | |
3422 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_484: 484-tone RU allocation | |
3423 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_484P242: 484+242 tone RU allocation | |
3424 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_996: 996-tone RU allocation | |
3425 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_996P484: 996+484 tone RU allocation | |
3426 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242: 996+484+242 tone RU allocation | |
3427 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_2x996: 2x996-tone RU allocation | |
3428 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484: 2x996+484 tone RU allocation | |
3429 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_3x996: 3x996-tone RU allocation | |
3430 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484: 3x996+484 tone RU allocation | |
3431 | * @NL80211_RATE_INFO_EHT_RU_ALLOC_4x996: 4x996-tone RU allocation | |
3432 | */ | |
3433 | enum nl80211_eht_ru_alloc { | |
3434 | NL80211_RATE_INFO_EHT_RU_ALLOC_26, | |
3435 | NL80211_RATE_INFO_EHT_RU_ALLOC_52, | |
3436 | NL80211_RATE_INFO_EHT_RU_ALLOC_52P26, | |
3437 | NL80211_RATE_INFO_EHT_RU_ALLOC_106, | |
3438 | NL80211_RATE_INFO_EHT_RU_ALLOC_106P26, | |
3439 | NL80211_RATE_INFO_EHT_RU_ALLOC_242, | |
3440 | NL80211_RATE_INFO_EHT_RU_ALLOC_484, | |
3441 | NL80211_RATE_INFO_EHT_RU_ALLOC_484P242, | |
3442 | NL80211_RATE_INFO_EHT_RU_ALLOC_996, | |
3443 | NL80211_RATE_INFO_EHT_RU_ALLOC_996P484, | |
3444 | NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242, | |
3445 | NL80211_RATE_INFO_EHT_RU_ALLOC_2x996, | |
3446 | NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484, | |
3447 | NL80211_RATE_INFO_EHT_RU_ALLOC_3x996, | |
3448 | NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484, | |
3449 | NL80211_RATE_INFO_EHT_RU_ALLOC_4x996, | |
3280 | 3450 | }; |
3281 | 3451 | |
3282 | 3452 | /** |
3318 | 3488 | * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1) |
3319 | 3489 | * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then |
3320 | 3490 | * non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc) |
3491 | * @NL80211_RATE_INFO_320_MHZ_WIDTH: 320 MHz bitrate | |
3492 | * @NL80211_RATE_INFO_EHT_MCS: EHT MCS index (u8, 0-15) | |
3493 | * @NL80211_RATE_INFO_EHT_NSS: EHT NSS value (u8, 1-8) | |
3494 | * @NL80211_RATE_INFO_EHT_GI: EHT guard interval identifier | |
3495 | * (u8, see &enum nl80211_eht_gi) | |
3496 | * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then | |
3497 | * non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc) | |
3321 | 3498 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use |
3322 | 3499 | */ |
3323 | 3500 | enum nl80211_rate_info { |
3339 | 3516 | NL80211_RATE_INFO_HE_GI, |
3340 | 3517 | NL80211_RATE_INFO_HE_DCM, |
3341 | 3518 | NL80211_RATE_INFO_HE_RU_ALLOC, |
3519 | NL80211_RATE_INFO_320_MHZ_WIDTH, | |
3520 | NL80211_RATE_INFO_EHT_MCS, | |
3521 | NL80211_RATE_INFO_EHT_NSS, | |
3522 | NL80211_RATE_INFO_EHT_GI, | |
3523 | NL80211_RATE_INFO_EHT_RU_ALLOC, | |
3342 | 3524 | |
3343 | 3525 | /* keep last */ |
3344 | 3526 | __NL80211_RATE_INFO_AFTER_LAST, |
3649 | 3831 | * capabilities IE |
3650 | 3832 | * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE: HE PPE thresholds information as |
3651 | 3833 | * defined in HE capabilities IE |
3652 | * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently | |
3653 | * defined | |
3654 | 3834 | * @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16), |
3655 | 3835 | * given for all 6 GHz band channels |
3836 | * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are | |
3837 | * advertised on this band/for this iftype (binary) | |
3838 | * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC: EHT MAC capabilities as in EHT | |
3839 | * capabilities element | |
3840 | * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY: EHT PHY capabilities as in EHT | |
3841 | * capabilities element | |
3842 | * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET: EHT supported NSS/MCS as in EHT | |
3843 | * capabilities element | |
3844 | * @NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE: EHT PPE thresholds information as | |
3845 | * defined in EHT capabilities element | |
3656 | 3846 | * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use |
3847 | * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined | |
3657 | 3848 | */ |
3658 | 3849 | enum nl80211_band_iftype_attr { |
3659 | 3850 | __NL80211_BAND_IFTYPE_ATTR_INVALID, |
3664 | 3855 | NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, |
3665 | 3856 | NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, |
3666 | 3857 | NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, |
3858 | NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, | |
3859 | NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC, | |
3860 | NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY, | |
3861 | NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET, | |
3862 | NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE, | |
3667 | 3863 | |
3668 | 3864 | /* keep last */ |
3669 | 3865 | __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, |
3808 | 4004 | * on this channel in current regulatory domain. |
3809 | 4005 | * @NL80211_FREQUENCY_ATTR_16MHZ: 16 MHz operation is allowed |
3810 | 4006 | * on this channel in current regulatory domain. |
4007 | * @NL80211_FREQUENCY_ATTR_NO_320MHZ: any 320 MHz channel using this channel | |
4008 | * as the primary or any of the secondary channels isn't possible | |
4009 | * @NL80211_FREQUENCY_ATTR_NO_EHT: EHT operation is not allowed on this channel | |
4010 | * in current regulatory domain. | |
3811 | 4011 | * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number |
3812 | 4012 | * currently defined |
3813 | 4013 | * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use |
3844 | 4044 | NL80211_FREQUENCY_ATTR_4MHZ, |
3845 | 4045 | NL80211_FREQUENCY_ATTR_8MHZ, |
3846 | 4046 | NL80211_FREQUENCY_ATTR_16MHZ, |
4047 | NL80211_FREQUENCY_ATTR_NO_320MHZ, | |
4048 | NL80211_FREQUENCY_ATTR_NO_EHT, | |
3847 | 4049 | |
3848 | 4050 | /* keep last */ |
3849 | 4051 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, |
4042 | 4244 | * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed |
4043 | 4245 | * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed |
4044 | 4246 | * @NL80211_RRF_NO_HE: HE operation not allowed |
4247 | * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed | |
4045 | 4248 | */ |
4046 | 4249 | enum nl80211_reg_rule_flags { |
4047 | 4250 | NL80211_RRF_NO_OFDM = 1<<0, |
4060 | 4263 | NL80211_RRF_NO_80MHZ = 1<<15, |
4061 | 4264 | NL80211_RRF_NO_160MHZ = 1<<16, |
4062 | 4265 | NL80211_RRF_NO_HE = 1<<17, |
4266 | NL80211_RRF_NO_320MHZ = 1<<18, | |
4063 | 4267 | }; |
4064 | 4268 | |
4065 | 4269 | #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR |
4557 | 4761 | * @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel |
4558 | 4762 | * @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel |
4559 | 4763 | * @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel |
4764 | * @NL80211_CHAN_WIDTH_320: 320 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 | |
4765 | * attribute must be provided as well | |
4560 | 4766 | */ |
4561 | 4767 | enum nl80211_chan_width { |
4562 | 4768 | NL80211_CHAN_WIDTH_20_NOHT, |
4572 | 4778 | NL80211_CHAN_WIDTH_4, |
4573 | 4779 | NL80211_CHAN_WIDTH_8, |
4574 | 4780 | NL80211_CHAN_WIDTH_16, |
4781 | NL80211_CHAN_WIDTH_320, | |
4575 | 4782 | }; |
4576 | 4783 | |
4577 | 4784 | /** |
4886 | 5093 | * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) |
4887 | 5094 | * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) |
4888 | 5095 | * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs |
5096 | * @NL80211_BAND_LC: light communication band (placeholder) | |
4889 | 5097 | * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace |
4890 | 5098 | * since newer kernel versions may support more bands |
4891 | 5099 | */ |
4895 | 5103 | NL80211_BAND_60GHZ, |
4896 | 5104 | NL80211_BAND_6GHZ, |
4897 | 5105 | NL80211_BAND_S1GHZ, |
5106 | NL80211_BAND_LC, | |
4898 | 5107 | |
4899 | 5108 | NUM_NL80211_BANDS, |
4900 | 5109 | }; |
5461 | 5670 | * => allows 8 of AP/GO that can have BI gcd >= min gcd |
5462 | 5671 | * |
5463 | 5672 | * numbers = [ #{STA} <= 2 ], channels = 2, max = 2 |
5464 | * => allows two STAs on different channels | |
5673 | * => allows two STAs on the same or on different channels | |
5465 | 5674 | * |
5466 | 5675 | * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 |
5467 | 5676 | * => allows a STA plus three P2P interfaces |
5506 | 5715 | * @NL80211_PLINK_ESTAB: mesh peer link is established |
5507 | 5716 | * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled |
5508 | 5717 | * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh |
5509 | * plink are discarded | |
5718 | * plink are discarded, except for authentication frames | |
5510 | 5719 | * @NUM_NL80211_PLINK_STATES: number of peer link states |
5511 | 5720 | * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states |
5512 | 5721 | */ |
5643 | 5852 | NL80211_TDLS_DISABLE_LINK, |
5644 | 5853 | }; |
5645 | 5854 | |
5646 | /* | |
5855 | /** | |
5647 | 5856 | * enum nl80211_ap_sme_features - device-integrated AP features |
5648 | * Reserved for future use, no bits are defined in | |
5649 | * NL80211_ATTR_DEVICE_AP_SME yet. | |
5857 | * @NL80211_AP_SME_SA_QUERY_OFFLOAD: SA Query procedures offloaded to driver | |
5858 | * when user space indicates support for SA Query procedures offload during | |
5859 | * "start ap" with %NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT. | |
5860 | */ | |
5650 | 5861 | enum nl80211_ap_sme_features { |
5651 | }; | |
5652 | */ | |
5862 | NL80211_AP_SME_SA_QUERY_OFFLOAD = 1 << 0, | |
5863 | }; | |
5653 | 5864 | |
5654 | 5865 | /** |
5655 | 5866 | * enum nl80211_feature_flags - device/driver features |
5949 | 6160 | * frame protection for all management frames exchanged during the |
5950 | 6161 | * negotiation and range measurement procedure. |
5951 | 6162 | * |
6163 | * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision | |
6164 | * detection and change announcemnts. | |
6165 | * | |
6166 | * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD: Driver running in AP mode supports | |
6167 | * FILS encryption and decryption for (Re)Association Request and Response | |
6168 | * frames. Userspace has to share FILS AAD details to the driver by using | |
6169 | * @NL80211_CMD_SET_FILS_AAD. | |
6170 | * | |
6171 | * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC | |
6172 | * detection. | |
6173 | * | |
5952 | 6174 | * @NUM_NL80211_EXT_FEATURES: number of extended features. |
5953 | 6175 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. |
5954 | 6176 | */ |
6013 | 6235 | NL80211_EXT_FEATURE_SECURE_LTF, |
6014 | 6236 | NL80211_EXT_FEATURE_SECURE_RTT, |
6015 | 6237 | NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, |
6238 | NL80211_EXT_FEATURE_BSS_COLOR, | |
6239 | NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, | |
6240 | NL80211_EXT_FEATURE_RADAR_BACKGROUND, | |
6016 | 6241 | |
6017 | 6242 | /* add new features before the definition below */ |
6018 | 6243 | NUM_NL80211_EXT_FEATURES, |
6911 | 7136 | * @NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK: negotiate for LMR feedback. Only |
6912 | 7137 | * valid if either %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED or |
6913 | 7138 | * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. |
7139 | * @NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR: optional. The BSS color of the | |
7140 | * responder. Only valid if %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED | |
7141 | * or %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED is set. | |
6914 | 7142 | * |
6915 | 7143 | * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal |
6916 | 7144 | * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number |
6930 | 7158 | NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED, |
6931 | 7159 | NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED, |
6932 | 7160 | NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK, |
7161 | NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR, | |
6933 | 7162 | |
6934 | 7163 | /* keep last */ |
6935 | 7164 | NUM_NL80211_PMSR_FTM_REQ_ATTR, |
7298 | 7527 | NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, |
7299 | 7528 | }; |
7300 | 7529 | |
7530 | /** | |
7531 | * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced | |
7532 | * multi-BSSID advertisements (EMA) in AP mode. | |
7533 | * Kernel uses some of these attributes to advertise driver's support for | |
7534 | * MBSSID and EMA. | |
7535 | * Remaining attributes should be used by the userspace to configure the | |
7536 | * features. | |
7537 | * | |
7538 | * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid | |
7539 | * | |
7540 | * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise | |
7541 | * the maximum number of MBSSID interfaces supported by the driver. | |
7542 | * Driver should indicate MBSSID support by setting | |
7543 | * wiphy->mbssid_max_interfaces to a value more than or equal to 2. | |
7544 | * | |
7545 | * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel | |
7546 | * to advertise the maximum profile periodicity supported by the driver | |
7547 | * if EMA is enabled. Driver should indicate EMA support to the userspace | |
7548 | * by setting wiphy->ema_max_profile_periodicity to | |
7549 | * a non-zero value. | |
7550 | * | |
7551 | * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of | |
7552 | * this BSS (u8) in the multiple BSSID set. | |
7553 | * Value must be set to 0 for the transmitting interface and non-zero for | |
7554 | * all non-transmitting interfaces. The userspace will be responsible | |
7555 | * for using unique indices for the interfaces. | |
7556 | * Range: 0 to wiphy->mbssid_max_interfaces-1. | |
7557 | * | |
7558 | * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for | |
7559 | * a non-transmitted profile which provides the interface index (u32) of | |
7560 | * the transmitted profile. The value must match one of the interface | |
7561 | * indices advertised by the kernel. Optional if the interface being set up | |
7562 | * is the transmitting one, however, if provided then the value must match | |
7563 | * the interface index of the same. | |
7564 | * | |
7565 | * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. | |
7566 | * Setting this flag is permitted only if the driver advertises EMA support | |
7567 | * by setting wiphy->ema_max_profile_periodicity to non-zero. | |
7568 | * | |
7569 | * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal | |
7570 | * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute | |
7571 | */ | |
7572 | enum nl80211_mbssid_config_attributes { | |
7573 | __NL80211_MBSSID_CONFIG_ATTR_INVALID, | |
7574 | ||
7575 | NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, | |
7576 | NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, | |
7577 | NL80211_MBSSID_CONFIG_ATTR_INDEX, | |
7578 | NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, | |
7579 | NL80211_MBSSID_CONFIG_ATTR_EMA, | |
7580 | ||
7581 | /* keep last */ | |
7582 | __NL80211_MBSSID_CONFIG_ATTR_LAST, | |
7583 | NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1, | |
7584 | }; | |
7585 | ||
7586 | /** | |
7587 | * enum nl80211_ap_settings_flags - AP settings flags | |
7588 | * | |
7589 | * @NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT: AP supports external | |
7590 | * authentication. | |
7591 | * @NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT: Userspace supports SA Query | |
7592 | * procedures offload to driver. If driver advertises | |
7593 | * %NL80211_AP_SME_SA_QUERY_OFFLOAD in AP SME features, userspace shall | |
7594 | * ignore SA Query procedures and validations when this flag is set by | |
7595 | * userspace. | |
7596 | */ | |
7597 | enum nl80211_ap_settings_flags { | |
7598 | NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = 1 << 0, | |
7599 | NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1, | |
7600 | }; | |
7601 | ||
7301 | 7602 | #endif /* __LINUX_NL80211_H */ |
274 | 274 | crypto_bignum_sub(prime, y, y) < 0 || |
275 | 275 | crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN, |
276 | 276 | MAX_ECC_PRIME_LEN, primebytelen) < 0) { |
277 | wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); | |
277 | wpa_printf(MSG_DEBUG, "EAP-pwd: Could not solve y"); | |
278 | 278 | goto fail; |
279 | 279 | } |
280 | 280 |
507 | 507 | return; |
508 | 508 | } |
509 | 509 | |
510 | for (i = 0, j = 0; i < P2P_MAX_REG_CLASSES; i++) { | |
510 | for (i = 0, j = 0; i < src->reg_classes; i++) { | |
511 | 511 | if (is_6ghz_op_class(src->reg_class[i].reg_class)) |
512 | 512 | continue; |
513 | 513 | os_memcpy(&dst->reg_class[j], &src->reg_class[i], |
19 | 19 | #define STATE_MACHINE_DATA struct ieee802_1x_cp_sm |
20 | 20 | #define STATE_MACHINE_DEBUG_PREFIX "CP" |
21 | 21 | |
22 | static u64 default_cs_id = CS_ID_GCM_AES_128; | |
22 | static u64 cs_id[] = { CS_ID_GCM_AES_128, CS_ID_GCM_AES_256 }; | |
23 | 23 | |
24 | 24 | /* The variable defined in clause 12 in IEEE Std 802.1X-2010 */ |
25 | 25 | enum connect_type { PENDING, UNAUTHENTICATED, AUTHENTICATED, SECURE }; |
209 | 209 | sm->replay_protect = sm->kay->macsec_replay_protect; |
210 | 210 | sm->validate_frames = sm->kay->macsec_validate; |
211 | 211 | |
212 | /* NOTE: now no other than default cipher suite (AES-GCM-128) */ | |
213 | 212 | sm->current_cipher_suite = sm->cipher_suite; |
214 | 213 | secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite); |
215 | 214 | |
472 | 471 | sm->orx = false; |
473 | 472 | sm->otx = false; |
474 | 473 | |
475 | sm->current_cipher_suite = default_cs_id; | |
476 | sm->cipher_suite = default_cs_id; | |
474 | sm->current_cipher_suite = cs_id[kay->macsec_csindex]; | |
475 | sm->cipher_suite = cs_id[kay->macsec_csindex]; | |
477 | 476 | sm->cipher_offset = CONFIDENTIALITY_OFFSET_0; |
478 | 477 | sm->confidentiality_offset = sm->cipher_offset; |
479 | 478 | sm->transmit_delay = MKA_LIFE_TIME; |
490 | 489 | secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); |
491 | 490 | secy_cp_control_confidentiality_offset(sm->kay, |
492 | 491 | sm->confidentiality_offset); |
492 | secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite); | |
493 | 493 | |
494 | 494 | SM_STEP_RUN(CP); |
495 | 495 |
220 | 220 | |
221 | 221 | wpa_printf(MSG_DEBUG, "\tKey Number............: %d", |
222 | 222 | be_to_host32(body->kn)); |
223 | /* TODO: Other than GCM-AES-128 case: MACsec Cipher Suite */ | |
224 | wpa_hexdump(MSG_DEBUG, "\tAES Key Wrap of SAK...:", body->sak, 24); | |
223 | if (body_len == 28) { | |
224 | wpa_hexdump(MSG_DEBUG, "\tAES Key Wrap of SAK...:", | |
225 | body->sak, 24); | |
226 | } else if (body_len > CS_ID_LEN - sizeof(body->kn)) { | |
227 | wpa_hexdump(MSG_DEBUG, "\tMACsec Cipher Suite...:", | |
228 | body->sak, CS_ID_LEN); | |
229 | wpa_hexdump(MSG_DEBUG, "\tAES Key Wrap of SAK...:", | |
230 | body->sak + CS_ID_LEN, | |
231 | body_len - CS_ID_LEN - sizeof(body->kn)); | |
232 | } | |
225 | 233 | } |
226 | 234 | |
227 | 235 | |
3455 | 3463 | struct ieee802_1x_kay * |
3456 | 3464 | ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, |
3457 | 3465 | bool macsec_replay_protect, u32 macsec_replay_window, |
3458 | u16 port, u8 priority, const char *ifname, const u8 *addr) | |
3466 | u16 port, u8 priority, u32 macsec_csindex, | |
3467 | const char *ifname, const u8 *addr) | |
3459 | 3468 | { |
3460 | 3469 | struct ieee802_1x_kay *kay; |
3461 | 3470 | |
3492 | 3501 | kay->dist_time = 0; |
3493 | 3502 | |
3494 | 3503 | kay->pn_exhaustion = PENDING_PN_EXHAUSTION; |
3495 | kay->macsec_csindex = DEFAULT_CS_INDEX; | |
3504 | kay->macsec_csindex = macsec_csindex; | |
3496 | 3505 | kay->mka_algindex = DEFAULT_MKA_ALG_INDEX; |
3497 | 3506 | kay->mka_version = MKA_VERSION_ID; |
3498 | 3507 |
239 | 239 | struct ieee802_1x_kay * |
240 | 240 | ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, |
241 | 241 | bool macsec_replay_protect, u32 macsec_replay_window, |
242 | u16 port, u8 priority, const char *ifname, const u8 *addr); | |
242 | u16 port, u8 priority, u32 macsec_csindex, | |
243 | const char *ifname, const u8 *addr); | |
243 | 244 | void ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay); |
244 | 245 | |
245 | 246 | struct ieee802_1x_mka_participant * |
32 | 32 | size_t num_othername; |
33 | 33 | struct http_logo *logo; |
34 | 34 | size_t num_logo; |
35 | const char *url; | |
35 | 36 | }; |
36 | 37 | |
37 | 38 | int soap_init_client(struct http_ctx *ctx, const char *address, |
63 | 63 | X509 *peer_issuer_issuer; |
64 | 64 | |
65 | 65 | const char *last_err; |
66 | const char *url; | |
66 | 67 | }; |
67 | 68 | |
68 | 69 | |
870 | 871 | X509 *cert, GENERAL_NAMES **names) |
871 | 872 | { |
872 | 873 | os_memset(hcert, 0, sizeof(*hcert)); |
874 | hcert->url = ctx->url ? ctx->url : ctx->svc_address; | |
873 | 875 | |
874 | 876 | *names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); |
875 | 877 | if (*names) |
1616 | 1618 | const char *fname, const char *ca_fname) |
1617 | 1619 | { |
1618 | 1620 | CURL *curl; |
1619 | FILE *f; | |
1621 | FILE *f = NULL; | |
1620 | 1622 | CURLcode res; |
1621 | 1623 | long http = 0; |
1624 | int ret = -1; | |
1622 | 1625 | |
1623 | 1626 | ctx->last_err = NULL; |
1627 | ctx->url = url; | |
1624 | 1628 | |
1625 | 1629 | wpa_printf(MSG_DEBUG, "curl: Download file from %s to %s (ca=%s)", |
1626 | 1630 | url, fname, ca_fname); |
1627 | 1631 | curl = curl_easy_init(); |
1628 | 1632 | if (curl == NULL) |
1629 | return -1; | |
1633 | goto fail; | |
1630 | 1634 | |
1631 | 1635 | f = fopen(fname, "wb"); |
1632 | if (f == NULL) { | |
1633 | curl_easy_cleanup(curl); | |
1634 | return -1; | |
1635 | } | |
1636 | if (!f) | |
1637 | goto fail; | |
1636 | 1638 | |
1637 | 1639 | curl_easy_setopt(curl, CURLOPT_URL, url); |
1638 | 1640 | if (ca_fname) { |
1654 | 1656 | ctx->last_err = curl_easy_strerror(res); |
1655 | 1657 | wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s", |
1656 | 1658 | ctx->last_err); |
1657 | curl_easy_cleanup(curl); | |
1658 | fclose(f); | |
1659 | return -1; | |
1659 | goto fail; | |
1660 | 1660 | } |
1661 | 1661 | |
1662 | 1662 | curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http); |
1664 | 1664 | if (http != 200) { |
1665 | 1665 | ctx->last_err = "HTTP download failed"; |
1666 | 1666 | wpa_printf(MSG_INFO, "HTTP download failed - code %ld", http); |
1667 | goto fail; | |
1668 | } | |
1669 | ||
1670 | ret = 0; | |
1671 | ||
1672 | fail: | |
1673 | ctx->url = NULL; | |
1674 | if (curl) | |
1667 | 1675 | curl_easy_cleanup(curl); |
1676 | if (f) | |
1668 | 1677 | fclose(f); |
1669 | return -1; | |
1670 | } | |
1671 | ||
1672 | curl_easy_cleanup(curl); | |
1673 | fclose(f); | |
1674 | ||
1675 | return 0; | |
1678 | ||
1679 | return ret; | |
1676 | 1680 | } |
1677 | 1681 | |
1678 | 1682 | |
1685 | 1689 | { |
1686 | 1690 | long http = 0; |
1687 | 1691 | CURLcode res; |
1688 | char *ret; | |
1692 | char *ret = NULL; | |
1689 | 1693 | CURL *curl; |
1690 | 1694 | struct curl_slist *curl_hdr = NULL; |
1691 | 1695 | |
1692 | 1696 | ctx->last_err = NULL; |
1697 | ctx->url = url; | |
1693 | 1698 | wpa_printf(MSG_DEBUG, "curl: HTTP POST to %s", url); |
1694 | 1699 | curl = setup_curl_post(ctx, url, ca_fname, username, password, |
1695 | 1700 | client_cert, client_key); |
1696 | 1701 | if (curl == NULL) |
1697 | return NULL; | |
1702 | goto fail; | |
1698 | 1703 | |
1699 | 1704 | if (content_type) { |
1700 | 1705 | char ct[200]; |
1714 | 1719 | ctx->last_err = curl_easy_strerror(res); |
1715 | 1720 | wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s", |
1716 | 1721 | ctx->last_err); |
1717 | free_curl_buf(ctx); | |
1718 | return NULL; | |
1722 | goto fail; | |
1719 | 1723 | } |
1720 | 1724 | |
1721 | 1725 | curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http); |
1723 | 1727 | if (http != 200) { |
1724 | 1728 | ctx->last_err = "HTTP POST failed"; |
1725 | 1729 | wpa_printf(MSG_INFO, "HTTP POST failed - code %ld", http); |
1726 | free_curl_buf(ctx); | |
1727 | return NULL; | |
1730 | goto fail; | |
1728 | 1731 | } |
1729 | 1732 | |
1730 | 1733 | if (ctx->curl_buf == NULL) |
1731 | return NULL; | |
1734 | goto fail; | |
1732 | 1735 | |
1733 | 1736 | ret = ctx->curl_buf; |
1734 | 1737 | if (resp_len) |
1738 | 1741 | |
1739 | 1742 | wpa_printf(MSG_MSGDUMP, "Server response:\n%s", ret); |
1740 | 1743 | |
1744 | fail: | |
1745 | free_curl_buf(ctx); | |
1746 | ctx->url = NULL; | |
1741 | 1747 | return ret; |
1742 | 1748 | } |
1743 | 1749 |
0 | 0 | BINALL=wpa_supplicant wpa_cli |
1 | ||
2 | ifndef CONFIG_NO_WPA_PASSPHRASE | |
3 | BINALL += wpa_passphrase | |
4 | endif | |
5 | 1 | |
6 | 2 | ALL = $(BINALL) |
7 | 3 | ALL += systemd/wpa_supplicant.service |
9 | 5 | ALL += systemd/wpa_supplicant-nl80211@.service |
10 | 6 | ALL += systemd/wpa_supplicant-wired@.service |
11 | 7 | ALL += dbus/fi.w1.wpa_supplicant1.service |
12 | ifdef CONFIG_BUILD_WPA_CLIENT_SO | |
13 | ALL += libwpa_client.so | |
14 | endif | |
15 | 8 | |
16 | 9 | EXTRA_TARGETS=dynamic_eap_methods |
17 | 10 | |
18 | 11 | CONFIG_FILE=.config |
19 | 12 | include ../src/build.rules |
13 | ||
14 | ifdef CONFIG_BUILD_WPA_CLIENT_SO | |
15 | # add the dependency this way to allow CONFIG_BUILD_WPA_CLIENT_SO | |
16 | # being set in the config which is read by build.rules | |
17 | _all: libwpa_client.so | |
18 | endif | |
19 | ||
20 | ifndef CONFIG_NO_WPA_PASSPHRASE | |
21 | # add the dependency this way to allow CONFIG_NO_WPA_PASSPHRASE | |
22 | # being set in the config which is read by build.rules | |
23 | _all: wpa_passphrase | |
24 | endif | |
20 | 25 | |
21 | 26 | ifdef LIBS |
22 | 27 | # If LIBS is set with some global build system defaults, clone those for |
2071 | 2076 | rm -f libwpa_client.a |
2072 | 2077 | rm -f libwpa_client.so |
2073 | 2078 | rm -f libwpa_test1 libwpa_test2 |
2079 | rm -f wpa_passphrase |
381 | 381 | HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; |
382 | 382 | |
383 | 383 | /* |
384 | * white-list capabilities that won't cause issues | |
384 | * include capabilities that won't cause issues | |
385 | 385 | * to connecting stations, while leaving the current |
386 | 386 | * capabilities intact (currently disabled SMPS). |
387 | 387 | */ |
902 | 902 | return; |
903 | 903 | } |
904 | 904 | |
905 | if (wpa_s->current_ssid) { | |
906 | int acs = 0; | |
907 | ||
905 | 908 | #ifdef CONFIG_ACS |
906 | if (wpa_s->current_ssid && wpa_s->current_ssid->acs) { | |
907 | wpa_s->assoc_freq = wpa_s->ap_iface->freq; | |
908 | wpa_s->current_ssid->frequency = wpa_s->ap_iface->freq; | |
909 | } | |
909 | acs = wpa_s->current_ssid->acs; | |
910 | 910 | #endif /* CONFIG_ACS */ |
911 | if (acs || (wpa_s->assoc_freq && wpa_s->ap_iface->freq && | |
912 | (int) wpa_s->assoc_freq != wpa_s->ap_iface->freq)) { | |
913 | wpa_s->assoc_freq = wpa_s->ap_iface->freq; | |
914 | wpa_s->current_ssid->frequency = wpa_s->ap_iface->freq; | |
915 | } | |
916 | } | |
911 | 917 | |
912 | 918 | wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); |
913 | 919 | |
1021 | 1027 | hapd_iface->extended_capa = wpa_s->extended_capa; |
1022 | 1028 | hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask; |
1023 | 1029 | hapd_iface->extended_capa_len = wpa_s->extended_capa_len; |
1030 | hapd_iface->drv_max_acl_mac_addrs = wpa_s->drv_max_acl_mac_addrs; | |
1024 | 1031 | |
1025 | 1032 | wpa_s->ap_iface->conf = conf = hostapd_config_defaults(); |
1026 | 1033 | if (conf == NULL) { |
1098 | 1105 | hapd_iface->bss[i]->ext_eapol_frame_io = |
1099 | 1106 | wpa_s->ext_eapol_frame_io; |
1100 | 1107 | #endif /* CONFIG_TESTING_OPTIONS */ |
1108 | ||
1109 | #ifdef CONFIG_WNM_AP | |
1110 | if (ssid->mode == WPAS_MODE_AP) | |
1111 | hapd_iface->bss[i]->conf->bss_transition = 1; | |
1112 | #endif /* CONFIG_WNM_AP */ | |
1101 | 1113 | } |
1102 | 1114 | |
1103 | 1115 | os_memcpy(hapd_iface->bss[0]->own_addr, wpa_s->own_addr, ETH_ALEN); |
1202 | 1214 | struct wpa_supplicant *wpa_s = ctx; |
1203 | 1215 | struct hostapd_frame_info fi; |
1204 | 1216 | os_memset(&fi, 0, sizeof(fi)); |
1217 | fi.freq = rx_mgmt->freq; | |
1205 | 1218 | fi.datarate = rx_mgmt->datarate; |
1206 | 1219 | fi.ssi_signal = rx_mgmt->ssi_signal; |
1207 | 1220 | ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame, |
1554 | 1567 | return pos - buf; |
1555 | 1568 | pos += ret; |
1556 | 1569 | return pos - buf; |
1570 | } | |
1571 | ||
1572 | ||
1573 | #ifdef CONFIG_WNM_AP | |
1574 | ||
1575 | int ap_ctrl_iface_disassoc_imminent(struct wpa_supplicant *wpa_s, | |
1576 | const char *buf) | |
1577 | { | |
1578 | struct hostapd_data *hapd; | |
1579 | ||
1580 | if (wpa_s->ap_iface) | |
1581 | hapd = wpa_s->ap_iface->bss[0]; | |
1582 | else | |
1583 | return -1; | |
1584 | return hostapd_ctrl_iface_disassoc_imminent(hapd, buf); | |
1585 | } | |
1586 | ||
1587 | ||
1588 | int ap_ctrl_iface_ess_disassoc(struct wpa_supplicant *wpa_s, const char *buf) | |
1589 | { | |
1590 | struct hostapd_data *hapd; | |
1591 | ||
1592 | if (wpa_s->ap_iface) | |
1593 | hapd = wpa_s->ap_iface->bss[0]; | |
1594 | else | |
1595 | return -1; | |
1596 | return hostapd_ctrl_iface_ess_disassoc(hapd, buf); | |
1597 | } | |
1598 | ||
1599 | ||
1600 | int ap_ctrl_iface_bss_tm_req(struct wpa_supplicant *wpa_s, const char *buf) | |
1601 | { | |
1602 | struct hostapd_data *hapd; | |
1603 | ||
1604 | if (wpa_s->ap_iface) | |
1605 | hapd = wpa_s->ap_iface->bss[0]; | |
1606 | else | |
1607 | return -1; | |
1608 | return hostapd_ctrl_iface_bss_tm_req(hapd, buf); | |
1609 | } | |
1610 | ||
1611 | #endif /* CONFIG_WNM_AP */ | |
1612 | ||
1613 | ||
1614 | int ap_ctrl_iface_acl_add_mac(struct wpa_supplicant *wpa_s, | |
1615 | enum macaddr_acl acl_type, | |
1616 | const char *buf) | |
1617 | { | |
1618 | struct hostapd_data *hapd; | |
1619 | ||
1620 | if (wpa_s->ap_iface) | |
1621 | hapd = wpa_s->ap_iface->bss[0]; | |
1622 | else | |
1623 | return -1; | |
1624 | ||
1625 | hapd->conf->macaddr_acl = acl_type; | |
1626 | ||
1627 | if (acl_type == ACCEPT_UNLESS_DENIED) | |
1628 | return hostapd_ctrl_iface_acl_add_mac(&hapd->conf->deny_mac, | |
1629 | &hapd->conf->num_deny_mac, | |
1630 | buf); | |
1631 | if (acl_type == DENY_UNLESS_ACCEPTED) | |
1632 | return hostapd_ctrl_iface_acl_add_mac( | |
1633 | &hapd->conf->accept_mac, | |
1634 | &hapd->conf->num_accept_mac, buf); | |
1635 | ||
1636 | return -1; | |
1637 | } | |
1638 | ||
1639 | ||
1640 | int ap_ctrl_iface_acl_del_mac(struct wpa_supplicant *wpa_s, | |
1641 | enum macaddr_acl acl_type, | |
1642 | const char *buf) | |
1643 | { | |
1644 | struct hostapd_data *hapd; | |
1645 | ||
1646 | if (wpa_s->ap_iface) | |
1647 | hapd = wpa_s->ap_iface->bss[0]; | |
1648 | else | |
1649 | return -1; | |
1650 | ||
1651 | hapd->conf->macaddr_acl = acl_type; | |
1652 | ||
1653 | if (acl_type == ACCEPT_UNLESS_DENIED) | |
1654 | return hostapd_ctrl_iface_acl_del_mac(&hapd->conf->deny_mac, | |
1655 | &hapd->conf->num_deny_mac, | |
1656 | buf); | |
1657 | if (acl_type == DENY_UNLESS_ACCEPTED) | |
1658 | return hostapd_ctrl_iface_acl_del_mac( | |
1659 | &hapd->conf->accept_mac, &hapd->conf->num_accept_mac, | |
1660 | buf); | |
1661 | ||
1662 | return -1; | |
1663 | } | |
1664 | ||
1665 | ||
1666 | int ap_ctrl_iface_acl_show_mac(struct wpa_supplicant *wpa_s, | |
1667 | enum macaddr_acl acl_type, char *buf, | |
1668 | size_t buflen) | |
1669 | { | |
1670 | struct hostapd_data *hapd; | |
1671 | ||
1672 | if (wpa_s->ap_iface) | |
1673 | hapd = wpa_s->ap_iface->bss[0]; | |
1674 | else | |
1675 | return -1; | |
1676 | ||
1677 | if (acl_type == ACCEPT_UNLESS_DENIED) | |
1678 | return hostapd_ctrl_iface_acl_show_mac(hapd->conf->deny_mac, | |
1679 | hapd->conf->num_deny_mac, | |
1680 | buf, buflen); | |
1681 | if (acl_type == DENY_UNLESS_ACCEPTED) | |
1682 | return hostapd_ctrl_iface_acl_show_mac( | |
1683 | hapd->conf->accept_mac, hapd->conf->num_accept_mac, | |
1684 | buf, buflen); | |
1685 | ||
1686 | return -1; | |
1687 | } | |
1688 | ||
1689 | ||
1690 | void ap_ctrl_iface_acl_clear_list(struct wpa_supplicant *wpa_s, | |
1691 | enum macaddr_acl acl_type) | |
1692 | { | |
1693 | struct hostapd_data *hapd; | |
1694 | ||
1695 | if (wpa_s->ap_iface) | |
1696 | hapd = wpa_s->ap_iface->bss[0]; | |
1697 | else | |
1698 | return; | |
1699 | ||
1700 | hapd->conf->macaddr_acl = acl_type; | |
1701 | ||
1702 | if (acl_type == ACCEPT_UNLESS_DENIED) | |
1703 | hostapd_ctrl_iface_acl_clear_list(&hapd->conf->deny_mac, | |
1704 | &hapd->conf->num_deny_mac); | |
1705 | else if (acl_type == DENY_UNLESS_ACCEPTED) | |
1706 | hostapd_ctrl_iface_acl_clear_list(&hapd->conf->accept_mac, | |
1707 | &hapd->conf->num_accept_mac); | |
1708 | } | |
1709 | ||
1710 | ||
1711 | int ap_ctrl_iface_disassoc_deny_mac(struct wpa_supplicant *wpa_s) | |
1712 | { | |
1713 | struct hostapd_data *hapd; | |
1714 | ||
1715 | if (wpa_s->ap_iface) | |
1716 | hapd = wpa_s->ap_iface->bss[0]; | |
1717 | else | |
1718 | return -1; | |
1719 | ||
1720 | return hostapd_disassoc_deny_mac(hapd); | |
1721 | } | |
1722 | ||
1723 | ||
1724 | int ap_ctrl_iface_disassoc_accept_mac(struct wpa_supplicant *wpa_s) | |
1725 | { | |
1726 | struct hostapd_data *hapd; | |
1727 | ||
1728 | if (wpa_s->ap_iface) | |
1729 | hapd = wpa_s->ap_iface->bss[0]; | |
1730 | else | |
1731 | return -1; | |
1732 | ||
1733 | return hostapd_disassoc_accept_mac(hapd); | |
1734 | } | |
1735 | ||
1736 | ||
1737 | int ap_ctrl_iface_set_acl(struct wpa_supplicant *wpa_s) | |
1738 | { | |
1739 | struct hostapd_data *hapd; | |
1740 | ||
1741 | if (wpa_s->ap_iface) | |
1742 | hapd = wpa_s->ap_iface->bss[0]; | |
1743 | else | |
1744 | return -1; | |
1745 | ||
1746 | return hostapd_set_acl(hapd); | |
1557 | 1747 | } |
1558 | 1748 | |
1559 | 1749 | #endif /* CONFIG_CTRL_IFACE */ |
8 | 8 | |
9 | 9 | #ifndef AP_H |
10 | 10 | #define AP_H |
11 | ||
12 | enum macaddr_acl; | |
11 | 13 | |
12 | 14 | int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, |
13 | 15 | struct wpa_ssid *ssid); |
37 | 39 | const char *txtaddr); |
38 | 40 | int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf, |
39 | 41 | size_t buflen, int verbose); |
42 | int ap_ctrl_iface_disassoc_imminent(struct wpa_supplicant *wpa_s, | |
43 | const char *buf); | |
44 | int ap_ctrl_iface_ess_disassoc(struct wpa_supplicant *wpa_s, const char *buf); | |
45 | int ap_ctrl_iface_bss_tm_req(struct wpa_supplicant *wpa_s, const char *buf); | |
46 | int ap_ctrl_iface_acl_add_mac(struct wpa_supplicant *wpa_s, | |
47 | enum macaddr_acl acl_type, const char *buf); | |
48 | int ap_ctrl_iface_acl_del_mac(struct wpa_supplicant *wpa_s, | |
49 | enum macaddr_acl acl_type, const char *buf); | |
50 | int ap_ctrl_iface_acl_show_mac(struct wpa_supplicant *wpa_s, | |
51 | enum macaddr_acl acl_type, char *buf, | |
52 | size_t buflen); | |
53 | void ap_ctrl_iface_acl_clear_list(struct wpa_supplicant *wpa_s, | |
54 | enum macaddr_acl acl_type); | |
55 | int ap_ctrl_iface_disassoc_deny_mac(struct wpa_supplicant *wpa_s); | |
56 | int ap_ctrl_iface_disassoc_accept_mac(struct wpa_supplicant *wpa_s); | |
57 | int ap_ctrl_iface_set_acl(struct wpa_supplicant *wpa_s); | |
40 | 58 | void ap_tx_status(void *ctx, const u8 *addr, |
41 | 59 | const u8 *buf, size_t len, int ack); |
42 | 60 | void ap_eapol_tx_status(void *ctx, const u8 *dst, |
2611 | 2611 | { INT(macsec_replay_window) }, |
2612 | 2612 | { INT_RANGE(macsec_port, 1, 65534) }, |
2613 | 2613 | { INT_RANGE(mka_priority, 0, 255) }, |
2614 | { INT_RANGE(macsec_csindex, 0, 1) }, | |
2614 | 2615 | { FUNC_KEY(mka_cak) }, |
2615 | 2616 | { FUNC_KEY(mka_ckn) }, |
2616 | 2617 | #endif /* CONFIG_MACSEC */ |
809 | 809 | INT(macsec_replay_window); |
810 | 810 | INT(macsec_port); |
811 | 811 | INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER); |
812 | INT(macsec_csindex); | |
812 | 813 | #endif /* CONFIG_MACSEC */ |
813 | 814 | #ifdef CONFIG_HS20 |
814 | 815 | INT(update_identifier); |
911 | 911 | int mka_priority; |
912 | 912 | |
913 | 913 | /** |
914 | * macsec_csindex - Cipher suite index for MACsec | |
915 | * | |
916 | * Range: 0-1 (default: 0) | |
917 | */ | |
918 | int macsec_csindex; | |
919 | ||
920 | /** | |
914 | 921 | * mka_ckn - MKA pre-shared CKN |
915 | 922 | */ |
916 | 923 | #define MACSEC_CKN_MAX_LEN 32 |
673 | 673 | } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { |
674 | 674 | os_free(wpa_s->dpp_configurator_params); |
675 | 675 | wpa_s->dpp_configurator_params = os_strdup(value); |
676 | #ifdef CONFIG_DPP2 | |
677 | dpp_controller_set_params(wpa_s->dpp, value); | |
678 | #endif /* CONFIG_DPP2 */ | |
676 | 679 | } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) { |
677 | 680 | wpa_s->dpp_init_max_tries = atoi(value); |
678 | 681 | } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) { |
8589 | 8592 | |
8590 | 8593 | if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0) |
8591 | 8594 | wpas_restore_permanent_mac_addr(wpa_s); |
8595 | ||
8596 | wpa_s->conf->ignore_old_scan_res = 0; | |
8592 | 8597 | } |
8593 | 8598 | |
8594 | 8599 | |
12016 | 12021 | } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) { |
12017 | 12022 | if (wpas_ap_update_beacon(wpa_s)) |
12018 | 12023 | reply_len = -1; |
12024 | } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { | |
12025 | if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { | |
12026 | if (ap_ctrl_iface_acl_add_mac(wpa_s, | |
12027 | DENY_UNLESS_ACCEPTED, | |
12028 | buf + 19) || | |
12029 | ap_ctrl_iface_set_acl(wpa_s)) | |
12030 | reply_len = -1; | |
12031 | } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { | |
12032 | if (ap_ctrl_iface_acl_del_mac(wpa_s, | |
12033 | DENY_UNLESS_ACCEPTED, | |
12034 | buf + 19) || | |
12035 | ap_ctrl_iface_set_acl(wpa_s) || | |
12036 | ap_ctrl_iface_disassoc_accept_mac(wpa_s)) | |
12037 | reply_len = -1; | |
12038 | } else if (os_strcmp(buf + 11, "SHOW") == 0) { | |
12039 | reply_len = ap_ctrl_iface_acl_show_mac( | |
12040 | wpa_s, DENY_UNLESS_ACCEPTED, | |
12041 | reply, reply_size); | |
12042 | } else if (os_strcmp(buf + 11, "CLEAR") == 0) { | |
12043 | ap_ctrl_iface_acl_clear_list(wpa_s, | |
12044 | DENY_UNLESS_ACCEPTED); | |
12045 | if (ap_ctrl_iface_set_acl(wpa_s) || | |
12046 | ap_ctrl_iface_disassoc_accept_mac(wpa_s)) | |
12047 | reply_len = -1; | |
12048 | } else { | |
12049 | reply_len = -1; | |
12050 | } | |
12051 | } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { | |
12052 | if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { | |
12053 | if (ap_ctrl_iface_acl_add_mac(wpa_s, | |
12054 | ACCEPT_UNLESS_DENIED, | |
12055 | buf + 17) || | |
12056 | ap_ctrl_iface_set_acl(wpa_s) || | |
12057 | ap_ctrl_iface_disassoc_deny_mac(wpa_s)) | |
12058 | reply_len = -1; | |
12059 | } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { | |
12060 | if (ap_ctrl_iface_acl_del_mac(wpa_s, | |
12061 | ACCEPT_UNLESS_DENIED, | |
12062 | buf + 17) || | |
12063 | ap_ctrl_iface_set_acl(wpa_s)) | |
12064 | reply_len = -1; | |
12065 | } else if (os_strcmp(buf + 9, "SHOW") == 0) { | |
12066 | reply_len = ap_ctrl_iface_acl_show_mac( | |
12067 | wpa_s, ACCEPT_UNLESS_DENIED, reply, reply_size); | |
12068 | } else if (os_strcmp(buf + 9, "CLEAR") == 0) { | |
12069 | ap_ctrl_iface_acl_clear_list(wpa_s, | |
12070 | ACCEPT_UNLESS_DENIED); | |
12071 | if (ap_ctrl_iface_set_acl(wpa_s)) | |
12072 | reply_len = -1; | |
12073 | } else { | |
12074 | reply_len = -1; | |
12075 | } | |
12019 | 12076 | #endif /* CONFIG_AP */ |
12020 | 12077 | } else if (os_strcmp(buf, "SUSPEND") == 0) { |
12021 | 12078 | wpas_notify_suspend(wpa_s->global); |
12111 | 12168 | if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18)) |
12112 | 12169 | reply_len = -1; |
12113 | 12170 | #endif /* CONFIG_WNM */ |
12171 | #ifdef CONFIG_WNM_AP | |
12172 | } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { | |
12173 | if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18)) | |
12174 | reply_len = -1; | |
12175 | } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { | |
12176 | if (ap_ctrl_iface_ess_disassoc(wpa_s, buf + 13)) | |
12177 | reply_len = -1; | |
12178 | } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { | |
12179 | if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11)) | |
12180 | reply_len = -1; | |
12181 | #endif /* CONFIG_WNM_AP */ | |
12114 | 12182 | } else if (os_strcmp(buf, "FLUSH") == 0) { |
12115 | 12183 | wpa_supplicant_ctrl_iface_flush(wpa_s); |
12116 | 12184 | } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) { |
12309 | 12377 | if (os_snprintf_error(reply_size, reply_len)) |
12310 | 12378 | reply_len = -1; |
12311 | 12379 | } |
12380 | } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) { | |
12381 | if (dpp_configurator_set(wpa_s->dpp, buf + 20) < 0) | |
12382 | reply_len = -1; | |
12312 | 12383 | } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { |
12313 | 12384 | if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0) |
12314 | 12385 | reply_len = -1; |
12332 | 12403 | } |
12333 | 12404 | } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { |
12334 | 12405 | if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0) |
12406 | reply_len = -1; | |
12407 | } else if (os_strncmp(buf, "DPP_CONF_SET ", 13) == 0) { | |
12408 | if (wpas_dpp_conf_set(wpa_s, buf + 12) < 0) | |
12335 | 12409 | reply_len = -1; |
12336 | 12410 | #ifdef CONFIG_DPP2 |
12337 | 12411 | } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) { |
1120 | 1120 | const struct wpa_dbus_property_desc *property_desc, |
1121 | 1121 | DBusMessageIter *iter, DBusError *error, void *user_data) |
1122 | 1122 | { |
1123 | const char *capabilities[13]; | |
1123 | const char *capabilities[14]; | |
1124 | 1124 | size_t num_items = 0; |
1125 | 1125 | struct wpa_global *global = user_data; |
1126 | 1126 | struct wpa_supplicant *wpa_s; |
1176 | 1176 | #endif /* CONFIG_SUITEB192 */ |
1177 | 1177 | if (ext_key_id_supported) |
1178 | 1178 | capabilities[num_items++] = "extended_key_id"; |
1179 | #ifndef CONFIG_WEP | |
1180 | capabilities[num_items++] = "wep_disabled"; | |
1181 | #endif /* !CONFIG_WEP */ | |
1179 | 1182 | |
1180 | 1183 | return wpas_dbus_simple_array_property_getter(iter, |
1181 | 1184 | DBUS_TYPE_STRING, |
3950 | 3953 | const char *auth_mode; |
3951 | 3954 | char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX]; |
3952 | 3955 | |
3953 | if (wpa_s->wpa_state != WPA_COMPLETED) { | |
3956 | if (wpa_s->wpa_state <= WPA_SCANNING) { | |
3954 | 3957 | auth_mode = "INACTIVE"; |
3955 | 3958 | } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || |
3956 | 3959 | wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { |
1 | 1 | * wpa_supplicant - DPP |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2018-2020, The Linux Foundation |
4 | * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
46 | 47 | const u8 *src, const u8 *bssid, |
47 | 48 | const u8 *data, size_t data_len, |
48 | 49 | enum offchannel_send_action_result result); |
50 | static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx); | |
49 | 51 | #ifdef CONFIG_DPP2 |
50 | 52 | static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, |
51 | 53 | void *timeout_ctx); |
52 | 54 | static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s); |
53 | 55 | static int wpas_dpp_process_conf_obj(void *ctx, |
54 | 56 | struct dpp_authentication *auth); |
57 | static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth); | |
55 | 58 | #endif /* CONFIG_DPP2 */ |
56 | 59 | |
57 | 60 | static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
294 | 297 | struct dpp_authentication *auth = wpa_s->dpp_auth; |
295 | 298 | enum dpp_status_error result; |
296 | 299 | |
297 | if (!auth || !auth->conn_status_requested) | |
300 | if ((!auth || !auth->conn_status_requested) && | |
301 | !dpp_tcp_conn_status_requested(wpa_s->dpp)) | |
298 | 302 | return; |
299 | 303 | |
300 | 304 | wpa_printf(MSG_DEBUG, |
370 | 374 | |
371 | 375 | eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); |
372 | 376 | |
373 | if (!auth || !auth->conn_status_requested) | |
374 | return; | |
375 | auth->conn_status_requested = 0; | |
377 | if ((!auth || !auth->conn_status_requested) && | |
378 | !dpp_tcp_conn_status_requested(wpa_s->dpp)) | |
379 | return; | |
380 | ||
376 | 381 | wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d", |
377 | 382 | result); |
378 | 383 | |
380 | 385 | channel_list_buf = wpas_dpp_scan_channel_list(wpa_s); |
381 | 386 | channel_list = channel_list_buf; |
382 | 387 | } |
388 | ||
389 | if (!auth || !auth->conn_status_requested) { | |
390 | dpp_tcp_send_conn_status(wpa_s->dpp, result, | |
391 | ssid ? ssid->ssid : | |
392 | wpa_s->dpp_last_ssid, | |
393 | ssid ? ssid->ssid_len : | |
394 | wpa_s->dpp_last_ssid_len, | |
395 | channel_list); | |
396 | os_free(channel_list_buf); | |
397 | return; | |
398 | } | |
399 | ||
400 | auth->conn_status_requested = 0; | |
383 | 401 | |
384 | 402 | msg = dpp_build_conn_status_result(auth, result, |
385 | 403 | ssid ? ssid->ssid : |
415 | 433 | { |
416 | 434 | struct dpp_authentication *auth = wpa_s->dpp_auth; |
417 | 435 | |
418 | if (auth && auth->conn_status_requested) | |
436 | if ((auth && auth->conn_status_requested) || | |
437 | dpp_tcp_conn_status_requested(wpa_s->dpp)) | |
419 | 438 | wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK); |
420 | 439 | } |
421 | 440 | |
758 | 777 | #endif /* CONFIG_DPP2 */ |
759 | 778 | |
760 | 779 | wpa_s->dpp_gas_client = 0; |
780 | wpa_s->dpp_gas_server = 0; | |
761 | 781 | |
762 | 782 | pos = os_strstr(cmd, " peer="); |
763 | 783 | if (!pos) |
873 | 893 | if (tcp) |
874 | 894 | return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, |
875 | 895 | wpa_s->conf->dpp_name, DPP_NETROLE_STA, |
876 | wpa_s, wpa_s, wpas_dpp_process_conf_obj); | |
896 | wpa_s, wpa_s, wpas_dpp_process_conf_obj, | |
897 | wpas_dpp_tcp_msg_sent); | |
877 | 898 | #endif /* CONFIG_DPP2 */ |
878 | 899 | |
879 | 900 | wpa_s->dpp_auth = auth; |
1123 | 1144 | return; |
1124 | 1145 | } |
1125 | 1146 | |
1147 | wpa_s->dpp_pkex_wait_auth_req = false; | |
1126 | 1148 | wpa_s->dpp_gas_client = 0; |
1149 | wpa_s->dpp_gas_server = 0; | |
1127 | 1150 | wpa_s->dpp_auth_ok_on_ack = 0; |
1128 | 1151 | wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s, |
1129 | 1152 | wpa_s->dpp_allowed_roles, |
1161 | 1184 | } |
1162 | 1185 | |
1163 | 1186 | |
1187 | void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s) | |
1188 | { | |
1189 | struct dpp_authentication *auth = wpa_s->dpp_auth; | |
1190 | int freq; | |
1191 | ||
1192 | if (!wpa_s->dpp_gas_server || !auth) | |
1193 | return; | |
1194 | ||
1195 | freq = auth->neg_freq > 0 ? auth->neg_freq : auth->curr_freq; | |
1196 | if (wpa_s->dpp_listen_work || (int) wpa_s->dpp_listen_freq == freq) | |
1197 | return; /* listen state is already in progress */ | |
1198 | ||
1199 | wpa_printf(MSG_DEBUG, "DPP: Start listen on %u MHz for GAS", freq); | |
1200 | wpa_s->dpp_in_response_listen = 1; | |
1201 | wpas_dpp_listen_start(wpa_s, freq); | |
1202 | } | |
1203 | ||
1204 | ||
1164 | 1205 | static void wpas_dpp_start_gas_server(struct wpa_supplicant *wpa_s) |
1165 | 1206 | { |
1166 | /* TODO: stop wait and start ROC */ | |
1207 | struct dpp_authentication *auth = wpa_s->dpp_auth; | |
1208 | ||
1209 | wpa_printf(MSG_DEBUG, | |
1210 | "DPP: Starting GAS server (curr_freq=%d neg_freq=%d dpp_listen_freq=%d dpp_listen_work=%d)", | |
1211 | auth->curr_freq, auth->neg_freq, wpa_s->dpp_listen_freq, | |
1212 | !!wpa_s->dpp_listen_work); | |
1213 | wpa_s->dpp_gas_server = 1; | |
1167 | 1214 | } |
1168 | 1215 | |
1169 | 1216 | |
1608 | 1655 | #endif /* CONFIG_DPP2 */ |
1609 | 1656 | |
1610 | 1657 | |
1658 | #ifdef CONFIG_DPP3 | |
1659 | static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx) | |
1660 | { | |
1661 | struct wpa_supplicant *wpa_s = eloop_ctx; | |
1662 | struct dpp_authentication *auth = wpa_s->dpp_auth; | |
1663 | ||
1664 | if (!auth || !auth->waiting_new_key) | |
1665 | return; | |
1666 | ||
1667 | wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key"); | |
1668 | wpas_dpp_start_gas_client(wpa_s); | |
1669 | } | |
1670 | #endif /* CONFIG_DPP3 */ | |
1671 | ||
1672 | ||
1611 | 1673 | static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, |
1612 | 1674 | enum gas_query_result result, |
1613 | 1675 | const struct wpabuf *adv_proto, |
1620 | 1682 | enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED; |
1621 | 1683 | unsigned int i; |
1622 | 1684 | |
1685 | eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL); | |
1623 | 1686 | wpa_s->dpp_gas_dialog_token = -1; |
1624 | 1687 | |
1625 | 1688 | if (!auth || (!auth->auth_success && !auth->reconfig_success) || |
1660 | 1723 | return; |
1661 | 1724 | } |
1662 | 1725 | #endif /* CONFIG_DPP2 */ |
1726 | #ifdef CONFIG_DPP3 | |
1727 | if (res == -3) { | |
1728 | wpa_printf(MSG_DEBUG, "DPP: New protocol key needed"); | |
1729 | eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s, | |
1730 | NULL); | |
1731 | return; | |
1732 | } | |
1733 | #endif /* CONFIG_DPP3 */ | |
1663 | 1734 | if (res < 0) { |
1664 | 1735 | wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); |
1665 | 1736 | goto fail; |
1721 | 1792 | } |
1722 | 1793 | |
1723 | 1794 | |
1795 | static void wpas_dpp_gas_client_timeout(void *eloop_ctx, void *timeout_ctx) | |
1796 | { | |
1797 | struct wpa_supplicant *wpa_s = eloop_ctx; | |
1798 | struct dpp_authentication *auth = wpa_s->dpp_auth; | |
1799 | ||
1800 | if (!wpa_s->dpp_gas_client || !auth || | |
1801 | (!auth->auth_success && !auth->reconfig_success)) | |
1802 | return; | |
1803 | ||
1804 | wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Config Response"); | |
1805 | wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); | |
1806 | dpp_auth_deinit(wpa_s->dpp_auth); | |
1807 | wpa_s->dpp_auth = NULL; | |
1808 | } | |
1809 | ||
1810 | ||
1724 | 1811 | static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s) |
1725 | 1812 | { |
1726 | 1813 | struct dpp_authentication *auth = wpa_s->dpp_auth; |
1746 | 1833 | |
1747 | 1834 | wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)", |
1748 | 1835 | MAC2STR(auth->peer_mac_addr), auth->curr_freq); |
1836 | ||
1837 | /* Use a 120 second timeout since the gas_query_req() operation could | |
1838 | * remain waiting indefinitely for the response if the Configurator | |
1839 | * keeps sending out comeback responses with additional delay. The | |
1840 | * DPP technical specification expects the Enrollee to continue sending | |
1841 | * out new Config Requests for 60 seconds, so this gives an extra 60 | |
1842 | * second time after the last expected new Config Request for the | |
1843 | * Configurator to determine what kind of configuration to provide. */ | |
1844 | eloop_register_timeout(120, 0, wpas_dpp_gas_client_timeout, | |
1845 | wpa_s, NULL); | |
1749 | 1846 | |
1750 | 1847 | res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq, |
1751 | 1848 | 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s); |
1945 | 2042 | status = dpp_conf_result_rx(auth, hdr, buf, len); |
1946 | 2043 | |
1947 | 2044 | if (status == DPP_STATUS_OK && auth->send_conn_status) { |
2045 | int freq; | |
2046 | ||
1948 | 2047 | wpa_msg(wpa_s, MSG_INFO, |
1949 | 2048 | DPP_EVENT_CONF_SENT "wait_conn_status=1"); |
1950 | 2049 | wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); |
1957 | 2056 | wpas_dpp_conn_status_result_wait_timeout, |
1958 | 2057 | wpa_s, NULL); |
1959 | 2058 | offchannel_send_action_done(wpa_s); |
1960 | wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq : | |
1961 | auth->curr_freq); | |
2059 | freq = auth->neg_freq ? auth->neg_freq : auth->curr_freq; | |
2060 | if (!wpa_s->dpp_in_response_listen || | |
2061 | (int) wpa_s->dpp_listen_freq != freq) | |
2062 | wpas_dpp_listen_start(wpa_s, freq); | |
1962 | 2063 | return; |
1963 | 2064 | } |
1964 | 2065 | offchannel_send_action_done(wpa_s); |
2024 | 2125 | wpas_dpp_post_process_config(wpa_s, auth); |
2025 | 2126 | |
2026 | 2127 | return res; |
2128 | } | |
2129 | ||
2130 | ||
2131 | static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth) | |
2132 | { | |
2133 | struct wpa_supplicant *wpa_s = ctx; | |
2134 | ||
2135 | wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback"); | |
2136 | ||
2137 | if (auth->connect_on_tx_status) { | |
2138 | auth->connect_on_tx_status = 0; | |
2139 | wpa_printf(MSG_DEBUG, | |
2140 | "DPP: Try to connect after completed configuration result"); | |
2141 | wpas_dpp_try_to_connect(wpa_s); | |
2142 | if (auth->conn_status_requested) { | |
2143 | wpa_printf(MSG_DEBUG, | |
2144 | "DPP: Start 15 second timeout for reporting connection status result"); | |
2145 | eloop_cancel_timeout( | |
2146 | wpas_dpp_conn_status_result_timeout, | |
2147 | wpa_s, NULL); | |
2148 | eloop_register_timeout( | |
2149 | 15, 0, wpas_dpp_conn_status_result_timeout, | |
2150 | wpa_s, NULL); | |
2151 | return true; | |
2152 | } | |
2153 | } | |
2154 | ||
2155 | return false; | |
2027 | 2156 | } |
2028 | 2157 | |
2029 | 2158 | |
2556 | 2685 | } |
2557 | 2686 | |
2558 | 2687 | |
2688 | #ifdef CONFIG_DPP2 | |
2689 | static int wpas_dpp_pkex_done(void *ctx, void *conn, | |
2690 | struct dpp_bootstrap_info *peer_bi) | |
2691 | { | |
2692 | struct wpa_supplicant *wpa_s = ctx; | |
2693 | const char *cmd = wpa_s->dpp_pkex_auth_cmd; | |
2694 | const char *pos; | |
2695 | u8 allowed_roles = DPP_CAPAB_CONFIGURATOR; | |
2696 | struct dpp_bootstrap_info *own_bi = NULL; | |
2697 | struct dpp_authentication *auth; | |
2698 | ||
2699 | if (!cmd) | |
2700 | cmd = ""; | |
2701 | wpa_printf(MSG_DEBUG, "DPP: Start authentication after PKEX (cmd: %s)", | |
2702 | cmd); | |
2703 | ||
2704 | pos = os_strstr(cmd, " own="); | |
2705 | if (pos) { | |
2706 | pos += 5; | |
2707 | own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); | |
2708 | if (!own_bi) { | |
2709 | wpa_printf(MSG_INFO, | |
2710 | "DPP: Could not find bootstrapping info for the identified local entry"); | |
2711 | return -1; | |
2712 | } | |
2713 | ||
2714 | if (peer_bi->curve != own_bi->curve) { | |
2715 | wpa_printf(MSG_INFO, | |
2716 | "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)", | |
2717 | peer_bi->curve->name, own_bi->curve->name); | |
2718 | return -1; | |
2719 | } | |
2720 | } | |
2721 | ||
2722 | pos = os_strstr(cmd, " role="); | |
2723 | if (pos) { | |
2724 | pos += 6; | |
2725 | if (os_strncmp(pos, "configurator", 12) == 0) | |
2726 | allowed_roles = DPP_CAPAB_CONFIGURATOR; | |
2727 | else if (os_strncmp(pos, "enrollee", 8) == 0) | |
2728 | allowed_roles = DPP_CAPAB_ENROLLEE; | |
2729 | else if (os_strncmp(pos, "either", 6) == 0) | |
2730 | allowed_roles = DPP_CAPAB_CONFIGURATOR | | |
2731 | DPP_CAPAB_ENROLLEE; | |
2732 | else | |
2733 | return -1; | |
2734 | } | |
2735 | ||
2736 | auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles, | |
2737 | 0, wpa_s->hw.modes, wpa_s->hw.num_modes); | |
2738 | if (!auth) | |
2739 | return -1; | |
2740 | ||
2741 | wpas_dpp_set_testing_options(wpa_s, auth); | |
2742 | if (dpp_set_configurator(auth, cmd) < 0) { | |
2743 | dpp_auth_deinit(auth); | |
2744 | return -1; | |
2745 | } | |
2746 | ||
2747 | return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name, | |
2748 | DPP_NETROLE_STA, wpas_dpp_process_conf_obj, | |
2749 | wpas_dpp_tcp_msg_sent); | |
2750 | } | |
2751 | #endif /* CONFIG_DPP2 */ | |
2752 | ||
2753 | ||
2754 | static int wpas_dpp_pkex_init(struct wpa_supplicant *wpa_s, | |
2755 | enum dpp_pkex_ver ver, | |
2756 | const struct hostapd_ip_addr *ipaddr, | |
2757 | int tcp_port) | |
2758 | { | |
2759 | struct dpp_pkex *pkex; | |
2760 | struct wpabuf *msg; | |
2761 | unsigned int wait_time; | |
2762 | bool v2 = ver != PKEX_VER_ONLY_1; | |
2763 | ||
2764 | wpa_printf(MSG_DEBUG, "DPP: Initiating PKEXv%d", v2 ? 2 : 1); | |
2765 | dpp_pkex_free(wpa_s->dpp_pkex); | |
2766 | wpa_s->dpp_pkex = NULL; | |
2767 | pkex = dpp_pkex_init(wpa_s, wpa_s->dpp_pkex_bi, wpa_s->own_addr, | |
2768 | wpa_s->dpp_pkex_identifier, | |
2769 | wpa_s->dpp_pkex_code, v2); | |
2770 | if (!pkex) | |
2771 | return -1; | |
2772 | pkex->forced_ver = ver != PKEX_VER_AUTO; | |
2773 | ||
2774 | if (ipaddr) { | |
2775 | #ifdef CONFIG_DPP2 | |
2776 | return dpp_tcp_pkex_init(wpa_s->dpp, pkex, ipaddr, tcp_port, | |
2777 | wpa_s, wpa_s, wpas_dpp_pkex_done); | |
2778 | #else /* CONFIG_DPP2 */ | |
2779 | return -1; | |
2780 | #endif /* CONFIG_DPP2 */ | |
2781 | } | |
2782 | ||
2783 | wpa_s->dpp_pkex = pkex; | |
2784 | msg = pkex->exchange_req; | |
2785 | wait_time = wpa_s->max_remain_on_chan; | |
2786 | if (wait_time > 2000) | |
2787 | wait_time = 2000; | |
2788 | pkex->freq = 2437; | |
2789 | wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR | |
2790 | " freq=%u type=%d", | |
2791 | MAC2STR(broadcast), pkex->freq, | |
2792 | v2 ? DPP_PA_PKEX_EXCHANGE_REQ : | |
2793 | DPP_PA_PKEX_V1_EXCHANGE_REQ); | |
2794 | offchannel_send_action(wpa_s, pkex->freq, broadcast, | |
2795 | wpa_s->own_addr, broadcast, | |
2796 | wpabuf_head(msg), wpabuf_len(msg), | |
2797 | wait_time, wpas_dpp_tx_pkex_status, 0); | |
2798 | if (wait_time == 0) | |
2799 | wait_time = 2000; | |
2800 | pkex->exch_req_wait_time = wait_time; | |
2801 | pkex->exch_req_tries = 1; | |
2802 | ||
2803 | return 0; | |
2804 | } | |
2805 | ||
2806 | ||
2559 | 2807 | static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx) |
2560 | 2808 | { |
2561 | 2809 | struct wpa_supplicant *wpa_s = eloop_ctx; |
2565 | 2813 | return; |
2566 | 2814 | if (pkex->exch_req_tries >= 5) { |
2567 | 2815 | if (wpas_dpp_pkex_next_channel(wpa_s, pkex) < 0) { |
2816 | #ifdef CONFIG_DPP3 | |
2817 | if (pkex->v2 && !pkex->forced_ver) { | |
2818 | wpa_printf(MSG_DEBUG, | |
2819 | "DPP: Fall back to PKEXv1"); | |
2820 | wpas_dpp_pkex_init(wpa_s, PKEX_VER_ONLY_1, | |
2821 | NULL, 0); | |
2822 | return; | |
2823 | } | |
2824 | #endif /* CONFIG_DPP3 */ | |
2568 | 2825 | wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL |
2569 | 2826 | "No response from PKEX peer"); |
2570 | 2827 | dpp_pkex_free(pkex); |
2648 | 2905 | wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR, |
2649 | 2906 | MAC2STR(src)); |
2650 | 2907 | |
2908 | if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_1 && v2) { | |
2909 | wpa_printf(MSG_DEBUG, | |
2910 | "DPP: Ignore PKEXv2 Exchange Request when configured to be PKEX v1 only"); | |
2911 | return; | |
2912 | } | |
2913 | if (wpa_s->dpp_pkex_ver == PKEX_VER_ONLY_2 && !v2) { | |
2914 | wpa_printf(MSG_DEBUG, | |
2915 | "DPP: Ignore PKEXv1 Exchange Request when configured to be PKEX v2 only"); | |
2916 | return; | |
2917 | } | |
2918 | ||
2651 | 2919 | /* TODO: Support multiple PKEX codes by iterating over all the enabled |
2652 | 2920 | * values here */ |
2653 | 2921 | |
2675 | 2943 | return; |
2676 | 2944 | } |
2677 | 2945 | |
2946 | wpa_s->dpp_pkex_wait_auth_req = false; | |
2678 | 2947 | msg = wpa_s->dpp_pkex->exchange_resp; |
2679 | 2948 | wait_time = wpa_s->max_remain_on_chan; |
2680 | 2949 | if (wait_time > 2000) |
2791 | 3060 | wpabuf_free(msg); |
2792 | 3061 | |
2793 | 3062 | wpas_dpp_pkex_finish(wpa_s, src, freq); |
3063 | wpa_s->dpp_pkex_wait_auth_req = true; | |
2794 | 3064 | } |
2795 | 3065 | |
2796 | 3066 | |
2958 | 3228 | } |
2959 | 3229 | |
2960 | 3230 | |
3231 | static void wpas_dpp_gas_initial_resp_timeout(void *eloop_ctx, | |
3232 | void *timeout_ctx) | |
3233 | { | |
3234 | struct wpa_supplicant *wpa_s = eloop_ctx; | |
3235 | struct dpp_authentication *auth = wpa_s->dpp_auth; | |
3236 | ||
3237 | if (!auth || !auth->waiting_config || !auth->config_resp_ctx) | |
3238 | return; | |
3239 | ||
3240 | wpa_printf(MSG_DEBUG, | |
3241 | "DPP: No configuration available from upper layers - send initial response with comeback delay"); | |
3242 | gas_server_set_comeback_delay(wpa_s->gas_server, auth->config_resp_ctx, | |
3243 | 500); | |
3244 | } | |
3245 | ||
3246 | ||
2961 | 3247 | static struct wpabuf * |
2962 | 3248 | wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa, |
2963 | const u8 *query, size_t query_len, u16 *comeback_delay) | |
3249 | const u8 *query, size_t query_len, int *comeback_delay) | |
2964 | 3250 | { |
2965 | 3251 | struct wpa_supplicant *wpa_s = ctx; |
2966 | 3252 | struct dpp_authentication *auth = wpa_s->dpp_auth; |
2992 | 3278 | MAC2STR(sa)); |
2993 | 3279 | resp = dpp_conf_req_rx(auth, query, query_len); |
2994 | 3280 | |
3281 | auth->gas_server_ctx = resp_ctx; | |
3282 | ||
2995 | 3283 | #ifdef CONFIG_DPP2 |
2996 | 3284 | if (!resp && auth->waiting_cert) { |
2997 | 3285 | wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); |
2998 | auth->cert_resp_ctx = resp_ctx; | |
3286 | auth->config_resp_ctx = resp_ctx; | |
2999 | 3287 | *comeback_delay = 500; |
3000 | 3288 | return NULL; |
3001 | 3289 | } |
3002 | 3290 | #endif /* CONFIG_DPP2 */ |
3003 | 3291 | |
3004 | if (!resp) | |
3292 | if (!resp && auth->waiting_config && | |
3293 | (auth->peer_bi || auth->tmp_peer_bi)) { | |
3294 | char *buf = NULL, *name = ""; | |
3295 | char band[200], *pos, *end; | |
3296 | int i, res, *opclass = auth->e_band_support; | |
3297 | char *mud_url = "N/A"; | |
3298 | ||
3299 | wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready"); | |
3300 | auth->config_resp_ctx = resp_ctx; | |
3301 | *comeback_delay = -1; | |
3302 | if (auth->e_name) { | |
3303 | size_t len = os_strlen(auth->e_name); | |
3304 | ||
3305 | buf = os_malloc(len * 4 + 1); | |
3306 | if (buf) { | |
3307 | printf_encode(buf, len * 4 + 1, | |
3308 | (const u8 *) auth->e_name, len); | |
3309 | name = buf; | |
3310 | } | |
3311 | } | |
3312 | band[0] = '\0'; | |
3313 | pos = band; | |
3314 | end = band + sizeof(band); | |
3315 | for (i = 0; opclass && opclass[i]; i++) { | |
3316 | res = os_snprintf(pos, end - pos, "%s%d", | |
3317 | pos == band ? "" : ",", opclass[i]); | |
3318 | if (os_snprintf_error(end - pos, res)) { | |
3319 | *pos = '\0'; | |
3320 | break; | |
3321 | } | |
3322 | pos += res; | |
3323 | } | |
3324 | if (auth->e_mud_url) { | |
3325 | size_t len = os_strlen(auth->e_mud_url); | |
3326 | ||
3327 | if (!has_ctrl_char((const u8 *) auth->e_mud_url, len)) | |
3328 | mud_url = auth->e_mud_url; | |
3329 | } | |
3330 | wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_NEEDED "peer=%d src=" | |
3331 | MACSTR " net_role=%s name=\"%s\" opclass=%s mud_url=%s", | |
3332 | auth->peer_bi ? auth->peer_bi->id : | |
3333 | auth->tmp_peer_bi->id, MAC2STR(sa), | |
3334 | dpp_netrole_str(auth->e_netrole), name, band, mud_url); | |
3335 | os_free(buf); | |
3336 | ||
3337 | eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, | |
3338 | NULL); | |
3339 | eloop_register_timeout(0, 50000, | |
3340 | wpas_dpp_gas_initial_resp_timeout, wpa_s, | |
3341 | NULL); | |
3342 | return NULL; | |
3343 | } | |
3344 | ||
3345 | auth->conf_resp = resp; | |
3346 | if (!resp) { | |
3005 | 3347 | wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); |
3006 | auth->conf_resp = resp; | |
3007 | auth->gas_server_ctx = resp_ctx; | |
3348 | dpp_auth_deinit(wpa_s->dpp_auth); | |
3349 | wpa_s->dpp_auth = NULL; | |
3350 | } | |
3008 | 3351 | return resp; |
3009 | 3352 | } |
3010 | 3353 | |
3034 | 3377 | return; |
3035 | 3378 | } |
3036 | 3379 | #endif /* CONFIG_DPP2 */ |
3380 | ||
3381 | #ifdef CONFIG_DPP3 | |
3382 | if (auth->waiting_new_key && ok) { | |
3383 | wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key"); | |
3384 | wpabuf_free(resp); | |
3385 | return; | |
3386 | } | |
3387 | #endif /* CONFIG_DPP3 */ | |
3037 | 3388 | |
3038 | 3389 | wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)", |
3039 | 3390 | ok); |
3156 | 3507 | wpa_printf(MSG_DEBUG, |
3157 | 3508 | "DPP: Starting network introduction protocol to derive PMKSA for " |
3158 | 3509 | MACSTR, MAC2STR(bss->bssid)); |
3510 | if (wpa_s->wpa_state == WPA_SCANNING) | |
3511 | wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state); | |
3159 | 3512 | |
3160 | 3513 | len = 5 + 4 + os_strlen(ssid->dpp_connector); |
3161 | 3514 | #ifdef CONFIG_DPP2 |
3235 | 3588 | } |
3236 | 3589 | #endif /* CONFIG_DPP3 */ |
3237 | 3590 | |
3591 | #ifdef CONFIG_TESTING_OPTIONS | |
3592 | if (dpp_test == DPP_TEST_INVALID_PROTOCOL_VERSION_PEER_DISC_REQ) { | |
3593 | wpa_printf(MSG_INFO, "DPP: TESTING - invalid Protocol Version"); | |
3594 | ver = 1; | |
3595 | } | |
3596 | #endif /* CONFIG_TESTING_OPTIONS */ | |
3597 | ||
3238 | 3598 | /* Protocol Version */ |
3239 | 3599 | wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); |
3240 | 3600 | wpabuf_put_le16(msg, 1); |
3270 | 3630 | { |
3271 | 3631 | struct dpp_bootstrap_info *own_bi; |
3272 | 3632 | const char *pos, *end; |
3273 | unsigned int wait_time; | |
3633 | #ifdef CONFIG_DPP3 | |
3634 | enum dpp_pkex_ver ver = PKEX_VER_AUTO; | |
3635 | #else /* CONFIG_DPP3 */ | |
3636 | enum dpp_pkex_ver ver = PKEX_VER_ONLY_1; | |
3637 | #endif /* CONFIG_DPP3 */ | |
3638 | int tcp_port = DPP_TCP_PORT; | |
3639 | struct hostapd_ip_addr *ipaddr = NULL; | |
3640 | #ifdef CONFIG_DPP2 | |
3641 | struct hostapd_ip_addr ipaddr_buf; | |
3642 | char *addr; | |
3643 | ||
3644 | pos = os_strstr(cmd, " tcp_port="); | |
3645 | if (pos) { | |
3646 | pos += 10; | |
3647 | tcp_port = atoi(pos); | |
3648 | } | |
3649 | ||
3650 | addr = get_param(cmd, " tcp_addr="); | |
3651 | if (addr) { | |
3652 | int res; | |
3653 | ||
3654 | res = hostapd_parse_ip_addr(addr, &ipaddr_buf); | |
3655 | os_free(addr); | |
3656 | if (res) | |
3657 | return -1; | |
3658 | ipaddr = &ipaddr_buf; | |
3659 | } | |
3660 | #endif /* CONFIG_DPP2 */ | |
3274 | 3661 | |
3275 | 3662 | pos = os_strstr(cmd, " own="); |
3276 | 3663 | if (!pos) |
3313 | 3700 | if (!wpa_s->dpp_pkex_code) |
3314 | 3701 | return -1; |
3315 | 3702 | |
3316 | if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) { | |
3317 | struct dpp_pkex *pkex; | |
3318 | struct wpabuf *msg; | |
3319 | bool v2 = os_strstr(cmd, " init=2") != NULL; | |
3320 | ||
3321 | wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX"); | |
3322 | dpp_pkex_free(wpa_s->dpp_pkex); | |
3323 | wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr, | |
3324 | wpa_s->dpp_pkex_identifier, | |
3325 | wpa_s->dpp_pkex_code, v2); | |
3326 | pkex = wpa_s->dpp_pkex; | |
3327 | if (!pkex) | |
3703 | pos = os_strstr(cmd, " ver="); | |
3704 | if (pos) { | |
3705 | int v; | |
3706 | ||
3707 | pos += 5; | |
3708 | v = atoi(pos); | |
3709 | if (v == 1) | |
3710 | ver = PKEX_VER_ONLY_1; | |
3711 | else if (v == 2) | |
3712 | ver = PKEX_VER_ONLY_2; | |
3713 | else | |
3328 | 3714 | return -1; |
3329 | ||
3330 | msg = pkex->exchange_req; | |
3331 | wait_time = wpa_s->max_remain_on_chan; | |
3332 | if (wait_time > 2000) | |
3333 | wait_time = 2000; | |
3334 | pkex->freq = 2437; | |
3335 | wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR | |
3336 | " freq=%u type=%d", | |
3337 | MAC2STR(broadcast), pkex->freq, | |
3338 | v2 ? DPP_PA_PKEX_EXCHANGE_REQ : | |
3339 | DPP_PA_PKEX_V1_EXCHANGE_REQ); | |
3340 | offchannel_send_action(wpa_s, pkex->freq, broadcast, | |
3341 | wpa_s->own_addr, broadcast, | |
3342 | wpabuf_head(msg), wpabuf_len(msg), | |
3343 | wait_time, wpas_dpp_tx_pkex_status, 0); | |
3344 | if (wait_time == 0) | |
3345 | wait_time = 2000; | |
3346 | pkex->exch_req_wait_time = wait_time; | |
3347 | pkex->exch_req_tries = 1; | |
3715 | } | |
3716 | wpa_s->dpp_pkex_ver = ver; | |
3717 | ||
3718 | if (os_strstr(cmd, " init=1")) { | |
3719 | if (wpas_dpp_pkex_init(wpa_s, ver, ipaddr, tcp_port) < 0) | |
3720 | return -1; | |
3721 | } else { | |
3722 | #ifdef CONFIG_DPP2 | |
3723 | dpp_controller_pkex_add(wpa_s->dpp, own_bi, | |
3724 | wpa_s->dpp_pkex_code, | |
3725 | wpa_s->dpp_pkex_identifier); | |
3726 | #endif /* CONFIG_DPP2 */ | |
3348 | 3727 | } |
3349 | 3728 | |
3350 | 3729 | /* TODO: Support multiple PKEX info entries */ |
3388 | 3767 | |
3389 | 3768 | void wpas_dpp_stop(struct wpa_supplicant *wpa_s) |
3390 | 3769 | { |
3391 | if (wpa_s->dpp_auth || wpa_s->dpp_pkex) | |
3770 | if (wpa_s->dpp_auth || wpa_s->dpp_pkex || wpa_s->dpp_pkex_wait_auth_req) | |
3392 | 3771 | offchannel_send_action_done(wpa_s); |
3393 | 3772 | dpp_auth_deinit(wpa_s->dpp_auth); |
3394 | 3773 | wpa_s->dpp_auth = NULL; |
3395 | 3774 | dpp_pkex_free(wpa_s->dpp_pkex); |
3396 | 3775 | wpa_s->dpp_pkex = NULL; |
3776 | wpa_s->dpp_pkex_wait_auth_req = false; | |
3397 | 3777 | if (wpa_s->dpp_gas_client && wpa_s->dpp_gas_dialog_token >= 0) |
3398 | 3778 | gas_query_stop(wpa_s->gas, wpa_s->dpp_gas_dialog_token); |
3399 | 3779 | } |
3443 | 3823 | eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL); |
3444 | 3824 | eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); |
3445 | 3825 | eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); |
3826 | eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL); | |
3827 | eloop_cancel_timeout(wpas_dpp_gas_client_timeout, wpa_s, NULL); | |
3446 | 3828 | #ifdef CONFIG_DPP2 |
3447 | 3829 | eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL); |
3448 | 3830 | eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout, |
3457 | 3839 | dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); |
3458 | 3840 | wpa_s->dpp_reconfig_id = NULL; |
3459 | 3841 | #endif /* CONFIG_DPP2 */ |
3842 | #ifdef CONFIG_DPP3 | |
3843 | eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL); | |
3844 | #endif /* CONFIG_DPP3 */ | |
3460 | 3845 | offchannel_send_action_done(wpa_s); |
3461 | 3846 | wpas_dpp_listen_stop(wpa_s); |
3462 | 3847 | wpas_dpp_stop(wpa_s); |
3468 | 3853 | } |
3469 | 3854 | |
3470 | 3855 | |
3856 | static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, | |
3857 | struct dpp_authentication *auth, bool tcp) | |
3858 | { | |
3859 | struct wpabuf *resp; | |
3860 | ||
3861 | resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len, | |
3862 | auth->e_netrole, true); | |
3863 | if (!resp) | |
3864 | return -1; | |
3865 | ||
3866 | if (tcp) { | |
3867 | auth->conf_resp_tcp = resp; | |
3868 | return 0; | |
3869 | } | |
3870 | ||
3871 | eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, NULL); | |
3872 | if (gas_server_set_resp(wpa_s->gas_server, auth->config_resp_ctx, | |
3873 | resp) < 0) { | |
3874 | wpa_printf(MSG_DEBUG, | |
3875 | "DPP: Could not find pending GAS response"); | |
3876 | wpabuf_free(resp); | |
3877 | return -1; | |
3878 | } | |
3879 | auth->conf_resp = resp; | |
3880 | return 0; | |
3881 | } | |
3882 | ||
3883 | ||
3884 | int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd) | |
3885 | { | |
3886 | int peer; | |
3887 | const char *pos; | |
3888 | struct dpp_authentication *auth = wpa_s->dpp_auth; | |
3889 | bool tcp = false; | |
3890 | ||
3891 | pos = os_strstr(cmd, " peer="); | |
3892 | if (!pos) | |
3893 | return -1; | |
3894 | peer = atoi(pos + 6); | |
3895 | #ifdef CONFIG_DPP2 | |
3896 | if (!auth || !auth->waiting_config || | |
3897 | (auth->peer_bi && | |
3898 | (unsigned int) peer != auth->peer_bi->id)) { | |
3899 | auth = dpp_controller_get_auth(wpa_s->dpp, peer); | |
3900 | tcp = true; | |
3901 | } | |
3902 | #endif /* CONFIG_DPP2 */ | |
3903 | ||
3904 | if (!auth || !auth->waiting_config) { | |
3905 | wpa_printf(MSG_DEBUG, | |
3906 | "DPP: No authentication exchange waiting for configuration information"); | |
3907 | return -1; | |
3908 | } | |
3909 | ||
3910 | if ((!auth->peer_bi || | |
3911 | (unsigned int) peer != auth->peer_bi->id) && | |
3912 | (!auth->tmp_peer_bi || | |
3913 | (unsigned int) peer != auth->tmp_peer_bi->id)) { | |
3914 | wpa_printf(MSG_DEBUG, "DPP: Peer mismatch"); | |
3915 | return -1; | |
3916 | } | |
3917 | ||
3918 | pos = os_strstr(cmd, " comeback="); | |
3919 | if (pos) { | |
3920 | eloop_cancel_timeout(wpas_dpp_gas_initial_resp_timeout, wpa_s, | |
3921 | NULL); | |
3922 | gas_server_set_comeback_delay(wpa_s->gas_server, | |
3923 | auth->config_resp_ctx, | |
3924 | atoi(pos + 10)); | |
3925 | return 0; | |
3926 | } | |
3927 | ||
3928 | if (dpp_set_configurator(auth, cmd) < 0) | |
3929 | return -1; | |
3930 | ||
3931 | auth->use_config_query = false; | |
3932 | auth->waiting_config = false; | |
3933 | return wpas_dpp_build_conf_resp(wpa_s, auth, tcp); | |
3934 | } | |
3935 | ||
3936 | ||
3471 | 3937 | #ifdef CONFIG_DPP2 |
3472 | 3938 | |
3473 | 3939 | int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) |
3481 | 3947 | config.msg_ctx = wpa_s; |
3482 | 3948 | config.cb_ctx = wpa_s; |
3483 | 3949 | config.process_conf_obj = wpas_dpp_process_conf_obj; |
3950 | config.tcp_msg_sent = wpas_dpp_tcp_msg_sent; | |
3484 | 3951 | if (cmd) { |
3485 | 3952 | pos = os_strstr(cmd, " tcp_port="); |
3486 | 3953 | if (pos) { |
3789 | 4256 | |
3790 | 4257 | wpas_dpp_chirp_stop(wpa_s); |
3791 | 4258 | wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; |
4259 | wpa_s->dpp_netrole = DPP_NETROLE_STA; | |
3792 | 4260 | wpa_s->dpp_qr_mutual = 0; |
3793 | 4261 | wpa_s->dpp_chirp_bi = bi; |
3794 | 4262 | wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi); |
3873 | 4341 | } |
3874 | 4342 | wpas_dpp_chirp_stop(wpa_s); |
3875 | 4343 | wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; |
4344 | wpa_s->dpp_netrole = DPP_NETROLE_STA; | |
3876 | 4345 | wpa_s->dpp_qr_mutual = 0; |
3877 | 4346 | wpa_s->dpp_reconfig_ssid = ssid; |
3878 | 4347 | wpa_s->dpp_reconfig_ssid_id = ssid->id; |
3882 | 4351 | wpa_s->dpp_chirp_listen = 0; |
3883 | 4352 | |
3884 | 4353 | return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); |
3885 | } | |
3886 | ||
3887 | ||
3888 | static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, | |
3889 | struct dpp_authentication *auth, bool tcp) | |
3890 | { | |
3891 | struct wpabuf *resp; | |
3892 | ||
3893 | resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len, | |
3894 | auth->e_netrole, true); | |
3895 | if (!resp) | |
3896 | return -1; | |
3897 | ||
3898 | if (tcp) { | |
3899 | auth->conf_resp_tcp = resp; | |
3900 | return 0; | |
3901 | } | |
3902 | ||
3903 | if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx, | |
3904 | resp) < 0) { | |
3905 | wpa_printf(MSG_DEBUG, | |
3906 | "DPP: Could not find pending GAS response"); | |
3907 | wpabuf_free(resp); | |
3908 | return -1; | |
3909 | } | |
3910 | auth->conf_resp = resp; | |
3911 | return 0; | |
3912 | 4354 | } |
3913 | 4355 | |
3914 | 4356 |
1 | 1 | * wpa_supplicant - DPP |
2 | 2 | * Copyright (c) 2017, Qualcomm Atheros, Inc. |
3 | 3 | * Copyright (c) 2018-2020, The Linux Foundation |
4 | * Copyright (c) 2022, Qualcomm Innovation Center, Inc. | |
4 | 5 | * |
5 | 6 | * This software may be distributed under the terms of the BSD license. |
6 | 7 | * See README for more details. |
22 | 23 | unsigned int freq, unsigned int duration); |
23 | 24 | void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, |
24 | 25 | unsigned int freq); |
26 | void wpas_dpp_tx_wait_expire(struct wpa_supplicant *wpa_s); | |
25 | 27 | void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, |
26 | 28 | const u8 *buf, size_t len, unsigned int freq); |
27 | 29 | int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd); |
40 | 42 | void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s); |
41 | 43 | int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd); |
42 | 44 | int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd); |
45 | int wpas_dpp_conf_set(struct wpa_supplicant *wpa_s, const char *cmd); | |
43 | 46 | |
44 | 47 | #endif /* DPP_SUPPLICANT_H */ |
147 | 147 | } |
148 | 148 | |
149 | 149 | |
150 | static void wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s) | |
151 | { | |
152 | struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid); | |
150 | static struct wpa_bss * | |
151 | wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s, const u8 *bssid) | |
152 | { | |
153 | struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid); | |
153 | 154 | |
154 | 155 | if (!bss) { |
155 | 156 | wpa_supplicant_update_scan_results(wpa_s); |
156 | 157 | |
157 | 158 | /* Get the BSS from the new scan results */ |
158 | bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid); | |
159 | bss = wpa_supplicant_get_new_bss(wpa_s, bssid); | |
159 | 160 | } |
160 | 161 | |
161 | 162 | if (bss) |
162 | 163 | wpa_s->current_bss = bss; |
164 | ||
165 | return bss; | |
163 | 166 | } |
164 | 167 | |
165 | 168 | |
171 | 174 | int res; |
172 | 175 | |
173 | 176 | if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) { |
174 | wpa_supplicant_update_current_bss(wpa_s); | |
177 | wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid); | |
175 | 178 | |
176 | 179 | if (wpa_s->current_ssid->ssid_len == 0) |
177 | 180 | return 0; /* current profile still in use */ |
248 | 251 | old_ssid = wpa_s->current_ssid; |
249 | 252 | wpa_s->current_ssid = ssid; |
250 | 253 | |
251 | wpa_supplicant_update_current_bss(wpa_s); | |
254 | wpa_supplicant_update_current_bss(wpa_s, wpa_s->bssid); | |
252 | 255 | |
253 | 256 | wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); |
254 | 257 | wpa_supplicant_initiate_eapol(wpa_s); |
3280 | 3283 | wpa_s->own_reconnect_req = 0; |
3281 | 3284 | |
3282 | 3285 | ft_completed = wpa_ft_is_completed(wpa_s->wpa); |
3286 | ||
3287 | if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { | |
3288 | wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID"); | |
3289 | wpa_supplicant_deauthenticate( | |
3290 | wpa_s, WLAN_REASON_DEAUTH_LEAVING); | |
3291 | return; | |
3292 | } | |
3293 | ||
3294 | if (ft_completed && | |
3295 | (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION)) { | |
3296 | wpa_msg(wpa_s, MSG_INFO, "Attempt to roam to " MACSTR, | |
3297 | MAC2STR(bssid)); | |
3298 | if (!wpa_supplicant_update_current_bss(wpa_s, bssid)) { | |
3299 | wpa_printf(MSG_ERROR, | |
3300 | "Can't find target AP's information!"); | |
3301 | return; | |
3302 | } | |
3303 | wpa_supplicant_assoc_update_ie(wpa_s); | |
3304 | } | |
3305 | ||
3283 | 3306 | if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) |
3284 | 3307 | return; |
3285 | 3308 | /* |
3289 | 3312 | */ |
3290 | 3313 | if (!ft_completed) |
3291 | 3314 | ft_completed = wpa_fils_is_completed(wpa_s->wpa); |
3292 | ||
3293 | if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { | |
3294 | wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID"); | |
3295 | wpa_supplicant_deauthenticate( | |
3296 | wpa_s, WLAN_REASON_DEAUTH_LEAVING); | |
3297 | return; | |
3298 | } | |
3299 | 3315 | |
3300 | 3316 | wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); |
3301 | 3317 | if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) { |
5737 | 5753 | case EVENT_UNPROT_BEACON: |
5738 | 5754 | wpas_event_unprot_beacon(wpa_s, &data->unprot_beacon); |
5739 | 5755 | break; |
5756 | case EVENT_TX_WAIT_EXPIRE: | |
5757 | #ifdef CONFIG_DPP | |
5758 | wpas_dpp_tx_wait_expire(wpa_s); | |
5759 | #endif /* CONFIG_DPP */ | |
5760 | break; | |
5740 | 5761 | default: |
5741 | 5762 | wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event); |
5742 | 5763 | break; |
381 | 381 | { |
382 | 382 | if (wpa_s->next_ssid == ssid) |
383 | 383 | wpa_s->next_ssid = NULL; |
384 | if (wpa_s->last_ssid == ssid) | |
385 | wpa_s->last_ssid = NULL; | |
386 | if (wpa_s->current_ssid == ssid) | |
387 | wpa_s->current_ssid = NULL; | |
384 | 388 | if (wpa_s->wpa) |
385 | 389 | wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); |
386 | 390 | if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s && |
8824 | 8824 | hapd->conf->ssid.wpa_psk = psk->next; |
8825 | 8825 | rem = psk; |
8826 | 8826 | psk = psk->next; |
8827 | os_free(rem); | |
8827 | bin_clear_free(rem, sizeof(*rem)); | |
8828 | 8828 | } else { |
8829 | 8829 | prev = psk; |
8830 | 8830 | psk = psk->next; |
2045 | 2045 | return wpa_ctrl_command(ctrl, "UPDATE_BEACON"); |
2046 | 2046 | } |
2047 | 2047 | |
2048 | ||
2049 | static int wpa_cli_cmd_accept_macacl(struct wpa_ctrl *ctrl, int argc, | |
2050 | char *argv[]) | |
2051 | { | |
2052 | return wpa_cli_cmd(ctrl, "ACCEPT_ACL", 1, argc, argv); | |
2053 | } | |
2054 | ||
2055 | ||
2056 | static int wpa_cli_cmd_deny_macacl(struct wpa_ctrl *ctrl, int argc, | |
2057 | char *argv[]) | |
2058 | { | |
2059 | return wpa_cli_cmd(ctrl, "DENY_ACL", 1, argc, argv); | |
2060 | } | |
2061 | ||
2048 | 2062 | #endif /* CONFIG_AP */ |
2049 | 2063 | |
2050 | 2064 | |
2891 | 2905 | } |
2892 | 2906 | |
2893 | 2907 | #endif /* CONFIG_WNM */ |
2908 | ||
2909 | ||
2910 | #ifdef CONFIG_WNM_AP | |
2911 | ||
2912 | static int wpa_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc, | |
2913 | char *argv[]) | |
2914 | { | |
2915 | return wpa_cli_cmd(ctrl, "DISASSOC_IMMINENT", 2, argc, argv); | |
2916 | } | |
2917 | ||
2918 | ||
2919 | static int wpa_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc, | |
2920 | char *argv[]) | |
2921 | { | |
2922 | return wpa_cli_cmd(ctrl, "ESS_DISASSOC", 3, argc, argv); | |
2923 | } | |
2924 | ||
2925 | ||
2926 | static int wpa_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc, | |
2927 | char *argv[]) | |
2928 | { | |
2929 | return wpa_cli_cmd(ctrl, "BSS_TM_REQ", 1, argc, argv); | |
2930 | } | |
2931 | ||
2932 | #endif /* CONFIG_WNM_AP */ | |
2894 | 2933 | |
2895 | 2934 | |
2896 | 2935 | static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[]) |
3598 | 3637 | { "update_beacon", wpa_cli_cmd_update_beacon, NULL, |
3599 | 3638 | cli_cmd_flag_none, |
3600 | 3639 | "= update Beacon frame contents"}, |
3640 | { "accept_acl", wpa_cli_cmd_accept_macacl, NULL, cli_cmd_flag_none, | |
3641 | "=Add/Delete/Show/Clear allow MAC ACL" }, | |
3642 | { "deny_acl", wpa_cli_cmd_deny_macacl, NULL, cli_cmd_flag_none, | |
3643 | "=Add/Delete/Show/Clear deny MAC ACL" }, | |
3601 | 3644 | #endif /* CONFIG_AP */ |
3602 | 3645 | { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none, |
3603 | 3646 | "= notification of suspend/hibernate" }, |
3844 | 3887 | " [neighbor=<BSSID>,<BSSID information>,<operating class>,<channel number>,<PHY type>[,<hexdump of optional subelements>]" |
3845 | 3888 | " = Send BSS Transition Management Query" }, |
3846 | 3889 | #endif /* CONFIG_WNM */ |
3890 | #ifdef CONFIG_WNM_AP | |
3891 | { "disassoc_imminent", wpa_cli_cmd_disassoc_imminent, NULL, cli_cmd_flag_none, | |
3892 | "= send Disassociation Imminent notification" }, | |
3893 | { "ess_disassoc", wpa_cli_cmd_ess_disassoc, NULL, cli_cmd_flag_none, | |
3894 | "= send ESS Dissassociation Imminent notification" }, | |
3895 | { "bss_tm_req", wpa_cli_cmd_bss_tm_req, NULL, cli_cmd_flag_none, | |
3896 | "= send BSS Transition Management Request" }, | |
3897 | #endif /* CONFIG_WNM_AP */ | |
3847 | 3898 | { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive, |
3848 | 3899 | "<params..> = Sent unprocessed command" }, |
3849 | 3900 | { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none, |
4241 | 4241 | */ |
4242 | 4242 | int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id) |
4243 | 4243 | { |
4244 | struct wpa_ssid *ssid; | |
4244 | struct wpa_ssid *ssid, *prev = wpa_s->current_ssid; | |
4245 | 4245 | int was_disabled; |
4246 | 4246 | |
4247 | 4247 | ssid = wpa_config_get_network(wpa_s->conf, id); |
4249 | 4249 | return -1; |
4250 | 4250 | wpas_notify_network_removed(wpa_s, ssid); |
4251 | 4251 | |
4252 | if (wpa_s->last_ssid == ssid) | |
4253 | wpa_s->last_ssid = NULL; | |
4254 | ||
4255 | if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) { | |
4252 | if (ssid == prev || !prev) { | |
4256 | 4253 | #ifdef CONFIG_SME |
4257 | 4254 | wpa_s->sme.prev_bssid_set = 0; |
4258 | 4255 | #endif /* CONFIG_SME */ |
4263 | 4260 | eapol_sm_invalidate_cached_session(wpa_s->eapol); |
4264 | 4261 | } |
4265 | 4262 | |
4266 | if (ssid == wpa_s->current_ssid) { | |
4263 | if (ssid == prev) { | |
4267 | 4264 | wpa_sm_set_config(wpa_s->wpa, NULL); |
4268 | 4265 | eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); |
4269 | 4266 | |
4326 | 4323 | |
4327 | 4324 | id = ssid->id; |
4328 | 4325 | ssid = ssid->next; |
4329 | if (wpa_s->last_ssid == remove_ssid) | |
4330 | wpa_s->last_ssid = NULL; | |
4331 | 4326 | wpas_notify_network_removed(wpa_s, remove_ssid); |
4332 | 4327 | wpa_config_remove_network(wpa_s->conf, id); |
4333 | 4328 | } |
6708 | 6703 | wpa_s->drv_flags2 = capa.flags2; |
6709 | 6704 | wpa_s->drv_enc = capa.enc; |
6710 | 6705 | wpa_s->drv_rrm_flags = capa.rrm_flags; |
6706 | wpa_s->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; | |
6711 | 6707 | wpa_s->probe_resp_offloads = capa.probe_resp_offloads; |
6712 | 6708 | wpa_s->max_scan_ssids = capa.max_scan_ssids; |
6713 | 6709 | wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids; |
13 | 13 | #include "common/defs.h" |
14 | 14 | #include "common/sae.h" |
15 | 15 | #include "common/wpa_ctrl.h" |
16 | #include "common/dpp.h" | |
16 | 17 | #include "crypto/sha384.h" |
17 | 18 | #include "eapol_supp/eapol_supp_sm.h" |
18 | 19 | #include "wps/wps_defs.h" |
910 | 911 | u64 drv_flags2; |
911 | 912 | unsigned int drv_enc; |
912 | 913 | unsigned int drv_rrm_flags; |
914 | unsigned int drv_max_acl_mac_addrs; | |
913 | 915 | |
914 | 916 | /* |
915 | 917 | * A bitmap of supported protocols for probe response offload. See |
1447 | 1449 | int dpp_auth_ok_on_ack; |
1448 | 1450 | int dpp_in_response_listen; |
1449 | 1451 | int dpp_gas_client; |
1452 | int dpp_gas_server; | |
1450 | 1453 | int dpp_gas_dialog_token; |
1451 | 1454 | u8 dpp_intro_bssid[ETH_ALEN]; |
1452 | 1455 | void *dpp_intro_network; |
1454 | 1457 | struct dpp_bootstrap_info *dpp_pkex_bi; |
1455 | 1458 | char *dpp_pkex_code; |
1456 | 1459 | char *dpp_pkex_identifier; |
1460 | enum dpp_pkex_ver dpp_pkex_ver; | |
1457 | 1461 | char *dpp_pkex_auth_cmd; |
1458 | 1462 | char *dpp_configurator_params; |
1459 | 1463 | struct os_reltime dpp_last_init; |
1466 | 1470 | u8 dpp_last_ssid[SSID_MAX_LEN]; |
1467 | 1471 | size_t dpp_last_ssid_len; |
1468 | 1472 | bool dpp_conf_backup_received; |
1473 | bool dpp_pkex_wait_auth_req; | |
1469 | 1474 | #ifdef CONFIG_DPP2 |
1470 | 1475 | struct dpp_pfs *dpp_pfs; |
1471 | 1476 | int dpp_pfs_fallback; |
102 | 102 | switch (co) { |
103 | 103 | case CONFIDENTIALITY_OFFSET_30: |
104 | 104 | return 30; |
105 | break; | |
106 | 105 | case CONFIDENTIALITY_OFFSET_50: |
107 | 106 | return 50; |
108 | 107 | default: |
240 | 239 | |
241 | 240 | res = ieee802_1x_kay_init(kay_ctx, policy, ssid->macsec_replay_protect, |
242 | 241 | ssid->macsec_replay_window, ssid->macsec_port, |
243 | ssid->mka_priority, wpa_s->ifname, | |
244 | wpa_s->own_addr); | |
242 | ssid->mka_priority, ssid->macsec_csindex, | |
243 | wpa_s->ifname, wpa_s->own_addr); | |
245 | 244 | /* ieee802_1x_kay_init() frees kay_ctx on failure */ |
246 | 245 | if (res == NULL) |
247 | 246 | return -1; |
355 | 355 | /* Remove the duplicated older network entry. */ |
356 | 356 | wpa_printf(MSG_DEBUG, "Remove duplicate network %d", ssid->id); |
357 | 357 | wpas_notify_network_removed(wpa_s, ssid); |
358 | if (wpa_s->current_ssid == ssid) | |
359 | wpa_s->current_ssid = NULL; | |
360 | 358 | wpa_config_remove_network(wpa_s->conf, ssid->id); |
361 | 359 | } |
362 | 360 | } |