diff mbox series

[v3] qmi: call-forwarding: fallback to basic forwarding info if no extended

Message ID 20241211165443.500978-1-ivo.g.dimitrov.75@gmail.com (mailing list archive)
State Accepted
Commit 37f7aea74270e2db9e0bdf072d6d8c45d75f6052
Headers show
Series [v3] qmi: call-forwarding: fallback to basic forwarding info if no extended | expand

Commit Message

Ivaylo Dimitrov Dec. 11, 2024, 4:54 p.m. UTC
At least Motorola Droid 4 does not support extended call forward info, so
fallback to basic
---
 drivers/qmimodem/call-forwarding.c | 80 ++++++++++++++++++------------
 1 file changed, 49 insertions(+), 31 deletions(-)

Comments

patchwork-bot+ofono@kernel.org Dec. 11, 2024, 6:30 p.m. UTC | #1
Hello:

This patch was applied to ofono.git (master)
by Denis Kenzior <denkenz@gmail.com>:

On Wed, 11 Dec 2024 18:54:43 +0200 you wrote:
> At least Motorola Droid 4 does not support extended call forward info, so
> fallback to basic
> ---
>  drivers/qmimodem/call-forwarding.c | 80 ++++++++++++++++++------------
>  1 file changed, 49 insertions(+), 31 deletions(-)

Here is the summary with links:
  - [v3] qmi: call-forwarding: fallback to basic forwarding info if no extended
    https://git.kernel.org/pub/scm/network/ofono/ofono.git/?id=37f7aea74270

You are awesome, thank you!
diff mbox series

Patch

diff --git a/drivers/qmimodem/call-forwarding.c b/drivers/qmimodem/call-forwarding.c
index e7ae3515..ad42e192 100644
--- a/drivers/qmimodem/call-forwarding.c
+++ b/drivers/qmimodem/call-forwarding.c
@@ -21,6 +21,13 @@  struct call_forwarding_data {
 	struct qmi_service *voice;
 };
 
+struct call_forwarding_info {
+	int8_t active;
+	uint8_t cls;
+	uint8_t len;
+	uint8_t number[];
+} __attribute__((__packed__));
+
 struct call_forwarding_info_ext {
 	uint8_t active;
 	uint8_t cls;
@@ -31,7 +38,7 @@  struct call_forwarding_info_ext {
 	uint8_t plan;
 	uint8_t len;
 	uint8_t number[];
-};
+} __attribute__((__packed__));
 
 static int forw_type_to_reason(int type)
 {
@@ -56,7 +63,7 @@  static int forw_type_to_reason(int type)
 
 static void set_fwd_cond(struct ofono_call_forwarding_condition *cond,
 				int status, int cls, int time, int type,
-				uint8_t *number, uint8_t nlen)
+				const uint8_t *number, uint8_t nlen)
 {
 	uint8_t maxlen = OFONO_MAX_PHONE_NUMBER_LENGTH;
 
@@ -76,56 +83,67 @@  static void query_cb(struct qmi_result *result, void *user_data)
 {
 	struct cb_data *cbd = user_data;
 	ofono_call_forwarding_query_cb_t cb = cbd->cb;
-	const uint8_t *p;
+	const void *p;
 	uint8_t num;
+	const uint8_t *end;
 	uint16_t length;
-
+	_auto_(l_free) struct ofono_call_forwarding_condition *list = NULL;
+	int i;
+	bool extended = false;
 	DBG("");
 
 	if (qmi_result_set_error(result, NULL))
 		goto error;
 
 	/*
-	 * we want extended info, because of the number type.
-	 * FIXME - shall we fallback to 0x10 if there is no extended info?
+	 * we want extended info if any, because of the number type.
 	 */
 	p = qmi_result_get(result, 0x16, &length);
-	if (p && length) {
-		struct ofono_call_forwarding_condition *list;
-		const uint8_t *end = p + length;
-		int i;
+	if (p && length)
+		extended = true;
+	else
+		p = qmi_result_get(result, 0x10, &length);
 
-		num = *p++;
+	if (!extended && (!p || !length))
+		goto error;
 
-		list = l_new(struct ofono_call_forwarding_condition, num);
+	end = p + length;
+	num = l_get_u8(p++);
+	list = l_new(struct ofono_call_forwarding_condition, num);
 
-		for (i = 0; i < num; i++) {
-			struct call_forwarding_info_ext *info = (void *)p;
+	for (i = 0; i < num; i++) {
+		if (extended) {
+			const struct call_forwarding_info_ext *fi = p;
+			const uint8_t *iend = p + sizeof(*fi);
 			int type;
 
-			/* do not try to access beyond buffer end */
-			if (p + sizeof(*info) > end ||
-					p + sizeof(*info) + info->len > end) {
-				l_free(list);
+			if (iend > end || iend + fi->len > end)
 				goto error;
-			}
 
-			if (info->type == 1)
-				type = OFONO_NUMBER_TYPE_INTERNATIONAL;
-			else
-				type = OFONO_NUMBER_TYPE_UNKNOWN;
+			type = fi->type == 1 ?
+					OFONO_NUMBER_TYPE_INTERNATIONAL :
+					OFONO_NUMBER_TYPE_UNKNOWN;
+			set_fwd_cond(&list[i], fi->active, fi->cls,
+					fi->time, type, fi->number, fi->len);
 
-			set_fwd_cond(&list[i], info->active, info->cls,
-					info->time, type, info->number,
-					info->len);
-			p += sizeof(*info) + info->len;
-		}
+			p += sizeof(*fi) + fi->len;
+		} else {
+			const struct call_forwarding_info *fi = p;
+			const uint8_t *iend = p + sizeof(*fi) + 1;
 
-		CALLBACK_WITH_SUCCESS(cb, num, list, cbd->data);
-		l_free(list);
-		return;
+			if (iend > end || iend + fi->len > end)
+				goto error;
+
+			p += sizeof(*fi) + fi->len;
+			set_fwd_cond(&list[i], fi->active, fi->cls,
+				l_get_u8(p++), OFONO_NUMBER_TYPE_UNKNOWN,
+				fi->number, fi->len);
+		}
 	}
 
+	CALLBACK_WITH_SUCCESS(cb, num, list, cbd->data);
+	return;
+
 error:
 	CALLBACK_WITH_FAILURE(cb, 0, NULL, cbd->data);
 }