diff mbox

[1/2] TDLS: Added dbus method to enable channel switching with TDLS peer

Message ID 1492085341-7930-1-git-send-email-n.chaprana@samsung.com
State Superseded
Headers show

Commit Message

Nishant Chaprana April 13, 2017, 12:09 p.m. UTC
Description: This patch adds "TDLSChannelSwitch" dbus method on
	     "fi.w1.wpa_supplicant1.Interface" interface to enable
	     channel switching with TDLS peer.

Signed-off-by: Nishant Chaprana <n.chaprana@samsung.com>
---
 wpa_supplicant/dbus/dbus_new.c          |   7 ++
 wpa_supplicant/dbus/dbus_new_handlers.c | 130 ++++++++++++++++++++++++++++++++
 wpa_supplicant/dbus/dbus_new_handlers.h |   2 +
 3 files changed, 139 insertions(+)

Comments

Dan Williams April 27, 2017, 4:12 p.m. UTC | #1
On Thu, 2017-04-13 at 17:39 +0530, Nishant Chaprana wrote:
> Description: This patch adds "TDLSChannelSwitch" dbus method on
> 	     "fi.w1.wpa_supplicant1.Interface" interface to enable
> 	     channel switching with TDLS peer.

Do we expect more TDLS-related methods?  If we expect more than say 3
or so, then it might make sense to make TDLS another D-Bus interface
that the wpa_supplicant "Interface" object implements.

More comments below...

> Signed-off-by: Nishant Chaprana <n.chaprana@samsung.com>
> ---
>  wpa_supplicant/dbus/dbus_new.c          |   7 ++
>  wpa_supplicant/dbus/dbus_new_handlers.c | 130
> ++++++++++++++++++++++++++++++++
>  wpa_supplicant/dbus/dbus_new_handlers.h |   2 +
>  3 files changed, 139 insertions(+)
> 
> diff --git a/wpa_supplicant/dbus/dbus_new.c
> b/wpa_supplicant/dbus/dbus_new.c
> index 0c355f7..0dce09e 100644
> --- a/wpa_supplicant/dbus/dbus_new.c
> +++ b/wpa_supplicant/dbus/dbus_new.c
> @@ -3086,6 +3086,13 @@ static const struct wpa_dbus_method_desc
> wpas_dbus_interface_methods[] = {
>  		  END_ARGS
>  	  }
>  	},
> +	{ "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
> +	  (WPADBusMethodHandler)
> wpas_dbus_handler_tdls_channel_switch,
> +	  {
> +		  { "args", "a{sv}", ARG_IN },
> +		  END_ARGS
> +	  }
> +	},
>  #endif /* CONFIG_TDLS */
>  	{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
>  	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
> diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c
> b/wpa_supplicant/dbus/dbus_new_handlers.c
> index 56e6aab..9092e7a 100644
> --- a/wpa_supplicant/dbus/dbus_new_handlers.c
> +++ b/wpa_supplicant/dbus/dbus_new_handlers.c
> @@ -2292,6 +2292,136 @@ DBusMessage *
> wpas_dbus_handler_tdls_teardown(DBusMessage *message,
>  	return NULL;
>  }
>  
> +/*
> + * wpas_dbus_handler_tdls_channel_switch - Enable channel switching
> with TDLS peer
> + * @message: Pointer to incoming dbus message
> + * @wpa_s: wpa_supplicant structure for a network interface
> + * Returns: NULL indicating success or DBus error message on failure
> + *
> + * Handler function for "TDLSChannelSwitch" method call of network
> interface.
> + */
> +DBusMessage * wpas_dbus_handler_tdls_channel_switch(DBusMessage
> *message,
> +						    struct
> wpa_supplicant *wpa_s)
> +{
> +	DBusMessageIter	iter, iter_dict;
> +	struct wpa_dbus_dict_entry entry;
> +	u8 peer[ETH_ALEN];
> +	struct hostapd_freq_params freq_params;
> +	u8 oper_class = 0;
> +	int ret;
> +	int is_peer_present = 0;
> +
> +	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
> +		wpa_printf(MSG_INFO,
> +			   "tdls_chanswitch: Only supported with
> external setup");
> +		return wpas_dbus_error_unknown_error(message, "tdls
> is not external setup");
> +	}
> +
> +	os_memset(&freq_params, 0, sizeof(freq_params));
> +
> +	dbus_message_iter_init(message, &iter);
> +
> +	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
> +		return wpas_dbus_error_invalid_args(message, NULL);
> +
> +	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
> +		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
> +			return wpas_dbus_error_invalid_args(message,
> NULL);
> +
> +		if (os_strcmp(entry.key, "PeerAddress") == 0 &&
> +		    entry.type == DBUS_TYPE_STRING) {
> +			if (hwaddr_aton(entry.str_value, peer)) {
> +				wpa_printf(MSG_DEBUG,
> +					   "tdls_chanswitch: Invalid
> address '%s'",
> +					   entry.str_value);
> +				wpa_dbus_dict_entry_clear(&entry);
> +				return
> wpas_dbus_error_invalid_args(message,
> +								    
> NULL);
> +			}
> +
> +			wpa_dbus_dict_entry_clear(&entry);
> +			is_peer_present = 1;
> +
> +		} else if (os_strcmp(entry.key, "OperClass") == 0 &&
> +			   entry.type == DBUS_TYPE_BYTE) {
> +			oper_class = entry.int32_value;
> +			wpa_dbus_dict_entry_clear(&entry);
> +
> +		} else if (os_strcmp(entry.key, "Frequency") == 0 &&
> +			   entry.type == DBUS_TYPE_INT32) {

Are these ever going to be negative?  If not, then they should probably
be UINT32.  Same goes for all the others below.

> +			freq_params.freq = entry.int32_value;
> +			wpa_dbus_dict_entry_clear(&entry);

Also, instead of calling wpa_dbus_dict_entry_clear() in every case,
just call it once at the bottom of the if/else/elseif calls...

> +		} else if (os_strcmp(entry.key, "SecChannelOffset")
> == 0 &&
> +			   entry.type == DBUS_TYPE_INT32) {
> +			freq_params.sec_channel_offset =
> entry.int32_value;
> +			wpa_dbus_dict_entry_clear(&entry);
> +
> +		} else if (os_strcmp(entry.key, "CenterFrequency1")
> == 0 &&
> +			   entry.type == DBUS_TYPE_INT32) {
> +			freq_params.center_freq1 =
> entry.int32_value;
> +			wpa_dbus_dict_entry_clear(&entry);
> +
> +		} else if (os_strcmp(entry.key, "CenterFrequency2")
> == 0 &&
> +			   entry.type == DBUS_TYPE_INT32) {
> +			freq_params.center_freq2 =
> entry.int32_value;
> +			wpa_dbus_dict_entry_clear(&entry);
> +
> +		} else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
> +			   entry.type == DBUS_TYPE_INT32) {
> +			freq_params.bandwidth = entry.int32_value;
> +			wpa_dbus_dict_entry_clear(&entry);
> +
> +		} else if (os_strcmp(entry.key, "HT") == 0 &&
> +			   entry.type == DBUS_TYPE_BOOLEAN) {
> +			freq_params.ht_enabled = entry.bool_value;
> +			wpa_dbus_dict_entry_clear(&entry);
> +
> +		} else if (os_strcmp(entry.key, "VHT") == 0 &&
> +			   entry.type == DBUS_TYPE_BOOLEAN) {
> +			freq_params.vht_enabled = entry.bool_value;
> +			wpa_dbus_dict_entry_clear(&entry);
> +
> +		} else {
> +			wpa_dbus_dict_entry_clear(&entry);
> +			return wpas_dbus_error_invalid_args(message,
> NULL);
> +		}

eg, here you'd call wpas_dbus_dict_entry_clear().  Leave the clear() in
the error case just above though.

Dan

> +	}
> +
> +	if (oper_class == 0) {
> +		wpa_printf(MSG_INFO,
> +			   "tdls_chanswitch: Invalid op class
> provided");
> +		return wpas_dbus_error_invalid_args(message,
> "Invalid op class provided");
> +	}
> +
> +	if (freq_params.freq == 0) {
> +		wpa_printf(MSG_INFO,
> +			   "tdls_chanswitch: Invalid freq
> provided");
> +		return wpas_dbus_error_invalid_args(message,
> "Invalid freq provided");
> +	}
> +
> +	if (is_peer_present == 0) {
> +		wpa_printf(MSG_DEBUG,
> +			   "tdls_chanswitch: peer address not
> provided");
> +		return wpas_dbus_error_invalid_args(message, "peer
> address not provided");
> +	}
> +
> +	wpa_printf(MSG_DEBUG, "DBUS TDLS_CHAN_SWITCH " MACSTR
> +		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d
> SEC_OFFSET %d%s%s",
> +		   MAC2STR(peer), oper_class, freq_params.freq,
> +		   freq_params.center_freq1,
> freq_params.center_freq2,
> +		   freq_params.bandwidth,
> freq_params.sec_channel_offset,
> +		   freq_params.ht_enabled ? " HT" : "",
> +		   freq_params.vht_enabled ? " VHT" : "");
> +
> +	ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer,
> oper_class,
> +					  &freq_params);
> +	if (ret)
> +		return wpas_dbus_error_unknown_error(message, "error
> processing TDLS channel switch");
> +
> +	return NULL;
> +}
> +
>  #endif /* CONFIG_TDLS */
>  
>  
> diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h
> b/wpa_supplicant/dbus/dbus_new_handlers.h
> index 3b8f096..3987c07 100644
> --- a/wpa_supplicant/dbus/dbus_new_handlers.h
> +++ b/wpa_supplicant/dbus/dbus_new_handlers.h
> @@ -213,6 +213,8 @@ DBusMessage *
> wpas_dbus_handler_tdls_status(DBusMessage *message,
>  					    struct wpa_supplicant
> *wpa_s);
>  DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
>  					      struct wpa_supplicant
> *wpa_s);
> +DBusMessage * wpas_dbus_handler_tdls_channel_switch(DBusMessage
> *message,
> +						    struct
> wpa_supplicant *wpa_s);
>  
>  DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage
> *message,
>  						struct
> wpa_supplicant *wpa_s);
diff mbox

Patch

diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 0c355f7..0dce09e 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -3086,6 +3086,13 @@  static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
 		  END_ARGS
 	  }
 	},
+	{ "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
+	  {
+		  { "args", "a{sv}", ARG_IN },
+		  END_ARGS
+	  }
+	},
 #endif /* CONFIG_TDLS */
 	{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 56e6aab..9092e7a 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -2292,6 +2292,136 @@  DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
 	return NULL;
 }
 
+/*
+ * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL indicating success or DBus error message on failure
+ *
+ * Handler function for "TDLSChannelSwitch" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
+						    struct wpa_supplicant *wpa_s)
+{
+	DBusMessageIter	iter, iter_dict;
+	struct wpa_dbus_dict_entry entry;
+	u8 peer[ETH_ALEN];
+	struct hostapd_freq_params freq_params;
+	u8 oper_class = 0;
+	int ret;
+	int is_peer_present = 0;
+
+	if (!wpa_tdls_is_external_setup(wpa_s->wpa)) {
+		wpa_printf(MSG_INFO,
+			   "tdls_chanswitch: Only supported with external setup");
+		return wpas_dbus_error_unknown_error(message, "tdls is not external setup");
+	}
+
+	os_memset(&freq_params, 0, sizeof(freq_params));
+
+	dbus_message_iter_init(message, &iter);
+
+	if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
+		return wpas_dbus_error_invalid_args(message, NULL);
+
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+			return wpas_dbus_error_invalid_args(message, NULL);
+
+		if (os_strcmp(entry.key, "PeerAddress") == 0 &&
+		    entry.type == DBUS_TYPE_STRING) {
+			if (hwaddr_aton(entry.str_value, peer)) {
+				wpa_printf(MSG_DEBUG,
+					   "tdls_chanswitch: Invalid address '%s'",
+					   entry.str_value);
+				wpa_dbus_dict_entry_clear(&entry);
+				return wpas_dbus_error_invalid_args(message,
+								    NULL);
+			}
+
+			wpa_dbus_dict_entry_clear(&entry);
+			is_peer_present = 1;
+
+		} else if (os_strcmp(entry.key, "OperClass") == 0 &&
+			   entry.type == DBUS_TYPE_BYTE) {
+			oper_class = entry.int32_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else if (os_strcmp(entry.key, "Frequency") == 0 &&
+			   entry.type == DBUS_TYPE_INT32) {
+			freq_params.freq = entry.int32_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else if (os_strcmp(entry.key, "SecChannelOffset") == 0 &&
+			   entry.type == DBUS_TYPE_INT32) {
+			freq_params.sec_channel_offset = entry.int32_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else if (os_strcmp(entry.key, "CenterFrequency1") == 0 &&
+			   entry.type == DBUS_TYPE_INT32) {
+			freq_params.center_freq1 = entry.int32_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else if (os_strcmp(entry.key, "CenterFrequency2") == 0 &&
+			   entry.type == DBUS_TYPE_INT32) {
+			freq_params.center_freq2 = entry.int32_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else if (os_strcmp(entry.key, "Bandwidth") == 0 &&
+			   entry.type == DBUS_TYPE_INT32) {
+			freq_params.bandwidth = entry.int32_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else if (os_strcmp(entry.key, "HT") == 0 &&
+			   entry.type == DBUS_TYPE_BOOLEAN) {
+			freq_params.ht_enabled = entry.bool_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else if (os_strcmp(entry.key, "VHT") == 0 &&
+			   entry.type == DBUS_TYPE_BOOLEAN) {
+			freq_params.vht_enabled = entry.bool_value;
+			wpa_dbus_dict_entry_clear(&entry);
+
+		} else {
+			wpa_dbus_dict_entry_clear(&entry);
+			return wpas_dbus_error_invalid_args(message, NULL);
+		}
+	}
+
+	if (oper_class == 0) {
+		wpa_printf(MSG_INFO,
+			   "tdls_chanswitch: Invalid op class provided");
+		return wpas_dbus_error_invalid_args(message, "Invalid op class provided");
+	}
+
+	if (freq_params.freq == 0) {
+		wpa_printf(MSG_INFO,
+			   "tdls_chanswitch: Invalid freq provided");
+		return wpas_dbus_error_invalid_args(message, "Invalid freq provided");
+	}
+
+	if (is_peer_present == 0) {
+		wpa_printf(MSG_DEBUG,
+			   "tdls_chanswitch: peer address not provided");
+		return wpas_dbus_error_invalid_args(message, "peer address not provided");
+	}
+
+	wpa_printf(MSG_DEBUG, "DBUS TDLS_CHAN_SWITCH " MACSTR
+		   " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s",
+		   MAC2STR(peer), oper_class, freq_params.freq,
+		   freq_params.center_freq1, freq_params.center_freq2,
+		   freq_params.bandwidth, freq_params.sec_channel_offset,
+		   freq_params.ht_enabled ? " HT" : "",
+		   freq_params.vht_enabled ? " VHT" : "");
+
+	ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class,
+					  &freq_params);
+	if (ret)
+		return wpas_dbus_error_unknown_error(message, "error processing TDLS channel switch");
+
+	return NULL;
+}
+
 #endif /* CONFIG_TDLS */
 
 
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index 3b8f096..3987c07 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -213,6 +213,8 @@  DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
 					    struct wpa_supplicant *wpa_s);
 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
 					      struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_tdls_channel_switch(DBusMessage *message,
+						    struct wpa_supplicant *wpa_s);
 
 DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
 						struct wpa_supplicant *wpa_s);