3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-27 03:09:38 +01:00

p2p: Try IP allocation during 4-Way handshake on client

This commit is contained in:
Andrew Zaborowski 2020-09-16 11:17:53 +02:00 committed by Denis Kenzior
parent 68cb9d38bf
commit ee4e1368d2

View File

@ -32,6 +32,8 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ell/ell.h> #include <ell/ell.h>
@ -97,7 +99,9 @@ struct p2p_device {
uint32_t conn_new_intf_cmd_id; uint32_t conn_new_intf_cmd_id;
struct wsc_enrollee *conn_enrollee; struct wsc_enrollee *conn_enrollee;
struct netconfig *conn_netconfig; struct netconfig *conn_netconfig;
struct l_settings *conn_netconfig_settings;
struct l_timeout *conn_dhcp_timeout; struct l_timeout *conn_dhcp_timeout;
char *conn_peer_ip;
struct p2p_wfd_properties *conn_own_wfd; struct p2p_wfd_properties *conn_own_wfd;
uint8_t conn_psk[32]; uint8_t conn_psk[32];
int conn_retry_count; int conn_retry_count;
@ -109,6 +113,7 @@ struct p2p_device {
unsigned int conn_go_scan_retry; unsigned int conn_go_scan_retry;
uint32_t conn_go_oper_freq; uint32_t conn_go_oper_freq;
uint8_t conn_peer_interface_addr[6]; uint8_t conn_peer_interface_addr[6];
struct p2p_capability_attr conn_peer_capability;
struct p2p_group_id_attr go_group_id; struct p2p_group_id_attr go_group_id;
struct ap_state *group; struct ap_state *group;
@ -446,6 +451,9 @@ static void p2p_connection_reset(struct p2p_device *dev)
if (dev->conn_netconfig) { if (dev->conn_netconfig) {
netconfig_destroy(dev->conn_netconfig); netconfig_destroy(dev->conn_netconfig);
dev->conn_netconfig = NULL; dev->conn_netconfig = NULL;
l_settings_free(dev->conn_netconfig_settings);
l_free(dev->conn_peer_ip);
dev->conn_peer_ip = NULL;
} }
if (dev->conn_new_intf_cmd_id) if (dev->conn_new_intf_cmd_id)
@ -761,6 +769,11 @@ static void p2p_netconfig_event_handler(enum netconfig_event event,
switch (event) { switch (event) {
case NETCONFIG_EVENT_CONNECTED: case NETCONFIG_EVENT_CONNECTED:
l_timeout_remove(dev->conn_dhcp_timeout); l_timeout_remove(dev->conn_dhcp_timeout);
if (!dev->conn_peer_ip)
dev->conn_peer_ip = netconfig_get_dhcp_server_ipv4(
dev->conn_netconfig);
p2p_peer_connect_done(dev); p2p_peer_connect_done(dev);
break; break;
default: default:
@ -786,10 +799,11 @@ static void p2p_dhcp_timeout_destroy(void *user_data)
dev->conn_dhcp_timeout = NULL; dev->conn_dhcp_timeout = NULL;
} }
static void p2p_start_dhcp_client(struct p2p_device *dev) static void p2p_start_client_netconfig(struct p2p_device *dev)
{ {
uint32_t ifindex = netdev_get_ifindex(dev->conn_netdev); uint32_t ifindex = netdev_get_ifindex(dev->conn_netdev);
unsigned int dhcp_timeout_val; unsigned int dhcp_timeout_val;
struct l_settings *settings;
if (!l_settings_get_uint(iwd_get_config(), "P2P", "DHCPTimeout", if (!l_settings_get_uint(iwd_get_config(), "P2P", "DHCPTimeout",
&dhcp_timeout_val)) &dhcp_timeout_val))
@ -803,9 +817,9 @@ static void p2p_start_dhcp_client(struct p2p_device *dev)
} }
} }
netconfig_configure(dev->conn_netconfig, p2p_dhcp_settings, settings = dev->conn_netconfig_settings ?: p2p_dhcp_settings;
dev->conn_addr, p2p_netconfig_event_handler, netconfig_configure(dev->conn_netconfig, settings, dev->conn_addr,
dev); p2p_netconfig_event_handler, dev);
dev->conn_dhcp_timeout = l_timeout_create(dhcp_timeout_val, dev->conn_dhcp_timeout = l_timeout_create(dhcp_timeout_val,
p2p_dhcp_timeout, dev, p2p_dhcp_timeout, dev,
p2p_dhcp_timeout_destroy); p2p_dhcp_timeout_destroy);
@ -827,7 +841,7 @@ static void p2p_netdev_connect_cb(struct netdev *netdev,
switch (result) { switch (result) {
case NETDEV_RESULT_OK: case NETDEV_RESULT_OK:
p2p_start_dhcp_client(dev); p2p_start_client_netconfig(dev);
break; break;
case NETDEV_RESULT_AUTHENTICATION_FAILED: case NETDEV_RESULT_AUTHENTICATION_FAILED:
case NETDEV_RESULT_ASSOCIATION_FAILED: case NETDEV_RESULT_ASSOCIATION_FAILED:
@ -916,6 +930,13 @@ static void p2p_netdev_event(struct netdev *netdev, enum netdev_event event,
}; };
} }
static const char *p2p_ip_to_string(uint32_t addr)
{
struct in_addr ia = { .s_addr = L_CPU_TO_BE32(addr) };
return inet_ntoa(ia);
}
static void p2p_handshake_event(struct handshake_state *hs, static void p2p_handshake_event(struct handshake_state *hs,
enum handshake_event event, void *user_data, enum handshake_event event, void *user_data,
...) ...)
@ -925,6 +946,24 @@ static void p2p_handshake_event(struct handshake_state *hs,
va_start(args, user_data); va_start(args, user_data);
switch (event) { switch (event) {
case HANDSHAKE_EVENT_COMPLETE:
{
struct p2p_device *dev = user_data;
struct l_settings *ip_config;
if (!hs->support_ip_allocation)
break;
ip_config = l_settings_new();
l_settings_set_string(ip_config, "IPv4", "Address",
p2p_ip_to_string(hs->client_ip_addr));
l_settings_set_string(ip_config, "IPv4", "Netmask",
p2p_ip_to_string(hs->subnet_mask));
dev->conn_netconfig_settings = ip_config;
dev->conn_peer_ip = l_strdup(p2p_ip_to_string(hs->go_ip_addr));
break;
}
case HANDSHAKE_EVENT_FAILED: case HANDSHAKE_EVENT_FAILED:
netdev_handshake_failed(hs, va_arg(args, int)); netdev_handshake_failed(hs, va_arg(args, int));
break; break;
@ -993,6 +1032,9 @@ static void p2p_try_connect_group(struct p2p_device *dev)
handshake_state_set_ssid(hs, bss->ssid, bss->ssid_len); handshake_state_set_ssid(hs, bss->ssid, bss->ssid_len);
handshake_state_set_pmk(hs, dev->conn_psk, 32); handshake_state_set_pmk(hs, dev->conn_psk, 32);
if (dev->conn_peer_capability.group_caps & P2P_GROUP_CAP_IP_ALLOCATION)
hs->support_ip_allocation = true;
r = netdev_connect(dev->conn_netdev, bss, hs, ie_iov, ie_num, r = netdev_connect(dev->conn_netdev, bss, hs, ie_iov, ie_num,
p2p_netdev_event, p2p_netdev_connect_cb, dev); p2p_netdev_event, p2p_netdev_connect_cb, dev);
if (r < 0) { if (r < 0) {
@ -1393,6 +1435,7 @@ static bool p2p_provision_scan_notify(int err, struct l_queue *bss_list,
l_debug("GO found in the scan results"); l_debug("GO found in the scan results");
dev->conn_wsc_bss = bss; dev->conn_wsc_bss = bss;
dev->conn_peer_capability = *capability;
p2p_device_interface_create(dev); p2p_device_interface_create(dev);
l_queue_remove(bss_list, bss); l_queue_remove(bss_list, bss);
l_queue_destroy(bss_list, l_queue_destroy(bss_list,
@ -4405,14 +4448,11 @@ static bool p2p_peer_get_connected_ip(struct l_dbus *dbus,
void *user_data) void *user_data)
{ {
struct p2p_peer *peer = user_data; struct p2p_peer *peer = user_data;
char *server_ip;
if (!p2p_peer_operational(peer)) if (!p2p_peer_operational(peer) || !peer->dev->conn_peer_ip)
return false; return false;
server_ip = netconfig_get_dhcp_server_ipv4(peer->dev->conn_netconfig); l_dbus_message_builder_append_basic(builder, 's', peer->dev->conn_peer_ip);
l_dbus_message_builder_append_basic(builder, 's', server_ip);
l_free(server_ip);
return true; return true;
} }