From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-msm@vger.kernel.org, Chris Lew <clew@codeaurora.org>
Subject: [PATCH v2 7/7] net: qrtr: Support decoding incoming v2 packets
Date: Tue, 10 Oct 2017 23:45:23 -0700 [thread overview]
Message-ID: <20171011064523.7902-8-bjorn.andersson@linaro.org> (raw)
In-Reply-To: <20171011064523.7902-1-bjorn.andersson@linaro.org>
Add the necessary logic for decoding incoming messages of version 2 as
well. Also make sure there's room for the bigger of version 1 and 2
headers in the code allocating skbs for outgoing messages.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
Changes since v1:
- Dropped __packed from struct qrtr_hdr_v2
net/qrtr/qrtr.c | 132 ++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 94 insertions(+), 38 deletions(-)
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index 7bca6ec892a5..e458ece96d3d 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -20,14 +20,15 @@
#include "qrtr.h"
-#define QRTR_PROTO_VER 1
+#define QRTR_PROTO_VER_1 1
+#define QRTR_PROTO_VER_2 3
/* auto-bind range */
#define QRTR_MIN_EPH_SOCKET 0x4000
#define QRTR_MAX_EPH_SOCKET 0x7fff
/**
- * struct qrtr_hdr - (I|R)PCrouter packet header
+ * struct qrtr_hdr_v1 - (I|R)PCrouter packet header version 1
* @version: protocol version
* @type: packet type; one of QRTR_TYPE_*
* @src_node_id: source node
@@ -37,7 +38,7 @@
* @dst_node_id: destination node
* @dst_port_id: destination port
*/
-struct qrtr_hdr {
+struct qrtr_hdr_v1 {
__le32 version;
__le32 type;
__le32 src_node_id;
@@ -48,6 +49,32 @@ struct qrtr_hdr {
__le32 dst_port_id;
} __packed;
+/**
+ * struct qrtr_hdr_v2 - (I|R)PCrouter packet header later versions
+ * @version: protocol version
+ * @type: packet type; one of QRTR_TYPE_*
+ * @flags: bitmask of QRTR_FLAGS_*
+ * @optlen: length of optional header data
+ * @size: length of packet, excluding this header and optlen
+ * @src_node_id: source node
+ * @src_port_id: source port
+ * @dst_node_id: destination node
+ * @dst_port_id: destination port
+ */
+struct qrtr_hdr_v2 {
+ u8 version;
+ u8 type;
+ u8 flags;
+ u8 optlen;
+ __le32 size;
+ __le16 src_node_id;
+ __le16 src_port_id;
+ __le16 dst_node_id;
+ __le16 dst_port_id;
+};
+
+#define QRTR_FLAGS_CONFIRM_RX BIT(0)
+
struct qrtr_cb {
u32 src_node;
u32 src_port;
@@ -58,7 +85,8 @@ struct qrtr_cb {
u8 confirm_rx;
};
-#define QRTR_HDR_SIZE sizeof(struct qrtr_hdr)
+#define QRTR_HDR_MAX_SIZE max_t(size_t, sizeof(struct qrtr_hdr_v1), \
+ sizeof(struct qrtr_hdr_v2))
struct qrtr_sock {
/* WARNING: sk must be the first member */
@@ -154,12 +182,12 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
int type, struct sockaddr_qrtr *from,
struct sockaddr_qrtr *to)
{
- struct qrtr_hdr *hdr;
+ struct qrtr_hdr_v1 *hdr;
size_t len = skb->len;
int rc = -ENODEV;
- hdr = skb_push(skb, QRTR_HDR_SIZE);
- hdr->version = cpu_to_le32(QRTR_PROTO_VER);
+ hdr = skb_push(skb, sizeof(*hdr));
+ hdr->version = cpu_to_le32(QRTR_PROTO_VER_1);
hdr->type = cpu_to_le32(type);
hdr->src_node_id = cpu_to_le32(from->sq_node);
hdr->src_port_id = cpu_to_le32(from->sq_port);
@@ -224,52 +252,80 @@ static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid)
int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
{
struct qrtr_node *node = ep->node;
- const struct qrtr_hdr *phdr = data;
+ const struct qrtr_hdr_v1 *v1;
+ const struct qrtr_hdr_v2 *v2;
struct sk_buff *skb;
struct qrtr_cb *cb;
- unsigned int psize;
unsigned int size;
- unsigned int type;
unsigned int ver;
- unsigned int dst;
+ size_t hdrlen;
- if (len < QRTR_HDR_SIZE || len & 3)
+ if (len & 3)
return -EINVAL;
- ver = le32_to_cpu(phdr->version);
- size = le32_to_cpu(phdr->size);
- type = le32_to_cpu(phdr->type);
- dst = le32_to_cpu(phdr->dst_port_id);
+ skb = netdev_alloc_skb(NULL, len);
+ if (!skb)
+ return -ENOMEM;
- psize = (size + 3) & ~3;
+ cb = (struct qrtr_cb *)skb->cb;
- if (ver != QRTR_PROTO_VER)
- return -EINVAL;
+ /* Version field in v1 is little endian, so this works for both cases */
+ ver = *(u8*)data;
- if (len != psize + QRTR_HDR_SIZE)
- return -EINVAL;
+ switch (ver) {
+ case QRTR_PROTO_VER_1:
+ v1 = data;
+ hdrlen = sizeof(*v1);
- if (dst != QRTR_PORT_CTRL && type != QRTR_TYPE_DATA)
- return -EINVAL;
+ cb->type = le32_to_cpu(v1->type);
+ cb->src_node = le32_to_cpu(v1->src_node_id);
+ cb->src_port = le32_to_cpu(v1->src_port_id);
+ cb->confirm_rx = !!v1->confirm_rx;
+ cb->dst_node = le32_to_cpu(v1->dst_node_id);
+ cb->dst_port = le32_to_cpu(v1->dst_port_id);
- skb = netdev_alloc_skb(NULL, len);
- if (!skb)
- return -ENOMEM;
+ size = le32_to_cpu(v1->size);
+ break;
+ case QRTR_PROTO_VER_2:
+ v2 = data;
+ hdrlen = sizeof(*v2) + v2->optlen;
+
+ cb->type = v2->type;
+ cb->confirm_rx = !!(v2->flags & QRTR_FLAGS_CONFIRM_RX);
+ cb->src_node = le16_to_cpu(v2->src_node_id);
+ cb->src_port = le16_to_cpu(v2->src_port_id);
+ cb->dst_node = le16_to_cpu(v2->dst_node_id);
+ cb->dst_port = le16_to_cpu(v2->dst_port_id);
+
+ if (cb->src_port == (u16)QRTR_PORT_CTRL)
+ cb->src_port = QRTR_PORT_CTRL;
+ if (cb->dst_port == (u16)QRTR_PORT_CTRL)
+ cb->dst_port = QRTR_PORT_CTRL;
+
+ size = le32_to_cpu(v2->size);
+ break;
+ default:
+ pr_err("qrtr: Invalid version %d\n", ver);
+ goto err;
+ }
- cb = (struct qrtr_cb *)skb->cb;
- cb->src_node = le32_to_cpu(phdr->src_node_id);
- cb->src_port = le32_to_cpu(phdr->src_port_id);
- cb->dst_node = le32_to_cpu(phdr->dst_node_id);
- cb->dst_port = le32_to_cpu(phdr->dst_port_id);
- cb->type = type;
- cb->confirm_rx = !!phdr->confirm_rx;
+ if (len != ALIGN(size, 4) + hdrlen)
+ goto err;
- skb_put_data(skb, data + QRTR_HDR_SIZE, size);
+ if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA)
+ goto err;
+
+ skb_put_data(skb, data + hdrlen, size);
skb_queue_tail(&node->rx_queue, skb);
schedule_work(&node->work);
return 0;
+
+err:
+ kfree_skb(skb);
+ return -EINVAL;
+
}
EXPORT_SYMBOL_GPL(qrtr_endpoint_post);
@@ -287,11 +343,11 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt)
const int pkt_len = sizeof(struct qrtr_ctrl_pkt);
struct sk_buff *skb;
- skb = alloc_skb(QRTR_HDR_SIZE + pkt_len, GFP_KERNEL);
+ skb = alloc_skb(QRTR_HDR_MAX_SIZE + pkt_len, GFP_KERNEL);
if (!skb)
return NULL;
- skb_reserve(skb, QRTR_HDR_SIZE);
+ skb_reserve(skb, QRTR_HDR_MAX_SIZE);
*pkt = skb_put_zero(skb, pkt_len);
return skb;
@@ -720,12 +776,12 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
}
plen = (len + 3) & ~3;
- skb = sock_alloc_send_skb(sk, plen + QRTR_HDR_SIZE,
+ skb = sock_alloc_send_skb(sk, plen + QRTR_HDR_MAX_SIZE,
msg->msg_flags & MSG_DONTWAIT, &rc);
if (!skb)
goto out_node;
- skb_reserve(skb, QRTR_HDR_SIZE);
+ skb_reserve(skb, QRTR_HDR_MAX_SIZE);
rc = memcpy_from_msg(skb_put(skb, len), msg, len);
if (rc) {
--
2.12.0
next prev parent reply other threads:[~2017-10-11 6:45 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-11 6:45 [PATCH v2 0/7] net: qrtr: Fixes and support receiving version 2 packets Bjorn Andersson
2017-10-11 6:45 ` [PATCH v2 1/7] net: qrtr: Invoke sk_error_report() after setting sk_err Bjorn Andersson
2017-10-11 6:45 ` [PATCH v2 2/7] net: qrtr: Move constants to header file Bjorn Andersson
2017-10-11 6:45 ` [PATCH v2 3/7] net: qrtr: Add control packet definition to uapi Bjorn Andersson
2017-10-11 6:45 ` [PATCH v2 4/7] net: qrtr: Pass source and destination to enqueue functions Bjorn Andersson
2017-10-11 6:45 ` [PATCH v2 5/7] net: qrtr: Clean up control packet handling Bjorn Andersson
2017-10-11 6:45 ` [PATCH v2 6/7] net: qrtr: Use sk_buff->cb in receive path Bjorn Andersson
2017-10-11 6:45 ` Bjorn Andersson [this message]
2017-10-11 22:38 ` [PATCH v2 0/7] net: qrtr: Fixes and support receiving version 2 packets David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171011064523.7902-8-bjorn.andersson@linaro.org \
--to=bjorn.andersson@linaro.org \
--cc=clew@codeaurora.org \
--cc=davem@davemloft.net \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).