diff --git a/src/handshake.c b/src/handshake.c index f36df572..146434c2 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -106,6 +106,8 @@ void handshake_state_free(struct handshake_state *s) l_free(s->supplicant_rsnxe); l_free(s->mde); l_free(s->fte); + l_free(s->fils_ip_req_ie); + l_free(s->fils_ip_resp_ie); if (s->erp_cache) erp_cache_put(s->erp_cache); diff --git a/src/handshake.h b/src/handshake.h index 31dce117..f3f6680b 100644 --- a/src/handshake.h +++ b/src/handshake.h @@ -140,6 +140,8 @@ struct handshake_state { uint32_t client_ip_addr; uint32_t subnet_mask; uint32_t go_ip_addr; + uint8_t *fils_ip_req_ie; + uint8_t *fils_ip_resp_ie; void *user_data; void (*free)(struct handshake_state *s); diff --git a/src/netdev.c b/src/netdev.c index 54856f6a..a5d1b8ed 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -292,6 +292,9 @@ static unsigned int netdev_populate_common_ies(struct netdev *netdev, c_iov = iov_ie_append(iov, n_iov, c_iov, hs->vendor_ies); + if (hs->fils_ip_req_ie) + c_iov = iov_ie_append(iov, n_iov, c_iov, hs->fils_ip_req_ie); + return c_iov; } @@ -2186,6 +2189,18 @@ process_resp_ies: qos_set = data; qos_len = ie_tlv_iter_get_length(&iter); break; + case IE_TYPE_FILS_IP_ADDRESS: + if (netdev->handshake->fils_ip_resp_ie) { + l_debug("Duplicate response FILS IP " + "Address Assignment IE"); + l_free(netdev->handshake-> + fils_ip_resp_ie); + } + + netdev->handshake->fils_ip_resp_ie = l_memdup( + data - 3, + ie_tlv_iter_get_length(&iter) + 3); + break; } } diff --git a/src/station.c b/src/station.c index f6237ade..9f00bfb3 100644 --- a/src/station.c +++ b/src/station.c @@ -924,6 +924,7 @@ static struct handshake_state *station_handshake_setup(struct station *station, struct handshake_state *hs; const struct iovec *vendor_ies; size_t iov_elems = 0; + struct ie_fils_ip_addr_request_info fils_ip_req; hs = netdev_handshake_state_new(station->netdev); @@ -940,6 +941,16 @@ static struct handshake_state *station_handshake_setup(struct station *station, vendor_ies = network_info_get_extra_ies(info, bss, &iov_elems); handshake_state_set_vendor_ies(hs, vendor_ies, iov_elems); + /* + * It can't hurt to try the FILS IP Address Assigment independent of + * which auth-proto is actually used. + */ + if (station->netconfig && netconfig_get_fils_ip_req(station->netconfig, + &fils_ip_req)) { + hs->fils_ip_req_ie = l_malloc(32); + ie_build_fils_ip_addr_request(&fils_ip_req, hs->fils_ip_req_ie); + } + return hs; not_supported: @@ -2444,6 +2455,35 @@ static void station_connect_ok(struct station *station) network_connected(station->connected_network); if (station->netconfig) { + if (hs->fils_ip_req_ie && hs->fils_ip_resp_ie) { + struct ie_fils_ip_addr_response_info info; + struct ie_tlv_iter iter; + int r; + + ie_tlv_iter_init(&iter, hs->fils_ip_resp_ie, + hs->fils_ip_resp_ie[1] + 2); + ie_tlv_iter_next(&iter); + r = ie_parse_fils_ip_addr_response(&iter, &info); + + if (r != 0) + l_debug("Error parsing the FILS IP Address " + "Assignment response: %s (%i)", + strerror(-r), -r); + else if (info.response_pending && + info.response_timeout) + l_debug("FILS IP Address Assignment response " + "is pending (unsupported)"); + else if (info.response_pending) + l_debug("FILS IP Address Assignment failed"); + else { + l_debug("FILS IP Address Assignment response " + "OK"); + netconfig_handle_fils_ip_resp( + station->netconfig, + &info); + } + } + if (L_WARN_ON(!netconfig_configure(station->netconfig, station_netconfig_event_handler, station)))