Skip to content

Commit 194ccc8

Browse files
anderssondavem330
authored andcommitted
net: qrtr: Support decoding incoming v2 packets
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f507a9b commit 194ccc8

File tree

1 file changed

+94
-38
lines changed

1 file changed

+94
-38
lines changed

net/qrtr/qrtr.c

Lines changed: 94 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020

2121
#include "qrtr.h"
2222

23-
#define QRTR_PROTO_VER 1
23+
#define QRTR_PROTO_VER_1 1
24+
#define QRTR_PROTO_VER_2 3
2425

2526
/* auto-bind range */
2627
#define QRTR_MIN_EPH_SOCKET 0x4000
2728
#define QRTR_MAX_EPH_SOCKET 0x7fff
2829

2930
/**
30-
* struct qrtr_hdr - (I|R)PCrouter packet header
31+
* struct qrtr_hdr_v1 - (I|R)PCrouter packet header version 1
3132
* @version: protocol version
3233
* @type: packet type; one of QRTR_TYPE_*
3334
* @src_node_id: source node
@@ -37,7 +38,7 @@
3738
* @dst_node_id: destination node
3839
* @dst_port_id: destination port
3940
*/
40-
struct qrtr_hdr {
41+
struct qrtr_hdr_v1 {
4142
__le32 version;
4243
__le32 type;
4344
__le32 src_node_id;
@@ -48,6 +49,32 @@ struct qrtr_hdr {
4849
__le32 dst_port_id;
4950
} __packed;
5051

52+
/**
53+
* struct qrtr_hdr_v2 - (I|R)PCrouter packet header later versions
54+
* @version: protocol version
55+
* @type: packet type; one of QRTR_TYPE_*
56+
* @flags: bitmask of QRTR_FLAGS_*
57+
* @optlen: length of optional header data
58+
* @size: length of packet, excluding this header and optlen
59+
* @src_node_id: source node
60+
* @src_port_id: source port
61+
* @dst_node_id: destination node
62+
* @dst_port_id: destination port
63+
*/
64+
struct qrtr_hdr_v2 {
65+
u8 version;
66+
u8 type;
67+
u8 flags;
68+
u8 optlen;
69+
__le32 size;
70+
__le16 src_node_id;
71+
__le16 src_port_id;
72+
__le16 dst_node_id;
73+
__le16 dst_port_id;
74+
};
75+
76+
#define QRTR_FLAGS_CONFIRM_RX BIT(0)
77+
5178
struct qrtr_cb {
5279
u32 src_node;
5380
u32 src_port;
@@ -58,7 +85,8 @@ struct qrtr_cb {
5885
u8 confirm_rx;
5986
};
6087

61-
#define QRTR_HDR_SIZE sizeof(struct qrtr_hdr)
88+
#define QRTR_HDR_MAX_SIZE max_t(size_t, sizeof(struct qrtr_hdr_v1), \
89+
sizeof(struct qrtr_hdr_v2))
6290

6391
struct qrtr_sock {
6492
/* WARNING: sk must be the first member */
@@ -154,12 +182,12 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
154182
int type, struct sockaddr_qrtr *from,
155183
struct sockaddr_qrtr *to)
156184
{
157-
struct qrtr_hdr *hdr;
185+
struct qrtr_hdr_v1 *hdr;
158186
size_t len = skb->len;
159187
int rc = -ENODEV;
160188

161-
hdr = skb_push(skb, QRTR_HDR_SIZE);
162-
hdr->version = cpu_to_le32(QRTR_PROTO_VER);
189+
hdr = skb_push(skb, sizeof(*hdr));
190+
hdr->version = cpu_to_le32(QRTR_PROTO_VER_1);
163191
hdr->type = cpu_to_le32(type);
164192
hdr->src_node_id = cpu_to_le32(from->sq_node);
165193
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)
224252
int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
225253
{
226254
struct qrtr_node *node = ep->node;
227-
const struct qrtr_hdr *phdr = data;
255+
const struct qrtr_hdr_v1 *v1;
256+
const struct qrtr_hdr_v2 *v2;
228257
struct sk_buff *skb;
229258
struct qrtr_cb *cb;
230-
unsigned int psize;
231259
unsigned int size;
232-
unsigned int type;
233260
unsigned int ver;
234-
unsigned int dst;
261+
size_t hdrlen;
235262

236-
if (len < QRTR_HDR_SIZE || len & 3)
263+
if (len & 3)
237264
return -EINVAL;
238265

239-
ver = le32_to_cpu(phdr->version);
240-
size = le32_to_cpu(phdr->size);
241-
type = le32_to_cpu(phdr->type);
242-
dst = le32_to_cpu(phdr->dst_port_id);
266+
skb = netdev_alloc_skb(NULL, len);
267+
if (!skb)
268+
return -ENOMEM;
243269

244-
psize = (size + 3) & ~3;
270+
cb = (struct qrtr_cb *)skb->cb;
245271

246-
if (ver != QRTR_PROTO_VER)
247-
return -EINVAL;
272+
/* Version field in v1 is little endian, so this works for both cases */
273+
ver = *(u8*)data;
248274

249-
if (len != psize + QRTR_HDR_SIZE)
250-
return -EINVAL;
275+
switch (ver) {
276+
case QRTR_PROTO_VER_1:
277+
v1 = data;
278+
hdrlen = sizeof(*v1);
251279

252-
if (dst != QRTR_PORT_CTRL && type != QRTR_TYPE_DATA)
253-
return -EINVAL;
280+
cb->type = le32_to_cpu(v1->type);
281+
cb->src_node = le32_to_cpu(v1->src_node_id);
282+
cb->src_port = le32_to_cpu(v1->src_port_id);
283+
cb->confirm_rx = !!v1->confirm_rx;
284+
cb->dst_node = le32_to_cpu(v1->dst_node_id);
285+
cb->dst_port = le32_to_cpu(v1->dst_port_id);
254286

255-
skb = netdev_alloc_skb(NULL, len);
256-
if (!skb)
257-
return -ENOMEM;
287+
size = le32_to_cpu(v1->size);
288+
break;
289+
case QRTR_PROTO_VER_2:
290+
v2 = data;
291+
hdrlen = sizeof(*v2) + v2->optlen;
292+
293+
cb->type = v2->type;
294+
cb->confirm_rx = !!(v2->flags & QRTR_FLAGS_CONFIRM_RX);
295+
cb->src_node = le16_to_cpu(v2->src_node_id);
296+
cb->src_port = le16_to_cpu(v2->src_port_id);
297+
cb->dst_node = le16_to_cpu(v2->dst_node_id);
298+
cb->dst_port = le16_to_cpu(v2->dst_port_id);
299+
300+
if (cb->src_port == (u16)QRTR_PORT_CTRL)
301+
cb->src_port = QRTR_PORT_CTRL;
302+
if (cb->dst_port == (u16)QRTR_PORT_CTRL)
303+
cb->dst_port = QRTR_PORT_CTRL;
304+
305+
size = le32_to_cpu(v2->size);
306+
break;
307+
default:
308+
pr_err("qrtr: Invalid version %d\n", ver);
309+
goto err;
310+
}
258311

259-
cb = (struct qrtr_cb *)skb->cb;
260-
cb->src_node = le32_to_cpu(phdr->src_node_id);
261-
cb->src_port = le32_to_cpu(phdr->src_port_id);
262-
cb->dst_node = le32_to_cpu(phdr->dst_node_id);
263-
cb->dst_port = le32_to_cpu(phdr->dst_port_id);
264-
cb->type = type;
265-
cb->confirm_rx = !!phdr->confirm_rx;
312+
if (len != ALIGN(size, 4) + hdrlen)
313+
goto err;
266314

267-
skb_put_data(skb, data + QRTR_HDR_SIZE, size);
315+
if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA)
316+
goto err;
317+
318+
skb_put_data(skb, data + hdrlen, size);
268319

269320
skb_queue_tail(&node->rx_queue, skb);
270321
schedule_work(&node->work);
271322

272323
return 0;
324+
325+
err:
326+
kfree_skb(skb);
327+
return -EINVAL;
328+
273329
}
274330
EXPORT_SYMBOL_GPL(qrtr_endpoint_post);
275331

@@ -287,11 +343,11 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt)
287343
const int pkt_len = sizeof(struct qrtr_ctrl_pkt);
288344
struct sk_buff *skb;
289345

290-
skb = alloc_skb(QRTR_HDR_SIZE + pkt_len, GFP_KERNEL);
346+
skb = alloc_skb(QRTR_HDR_MAX_SIZE + pkt_len, GFP_KERNEL);
291347
if (!skb)
292348
return NULL;
293349

294-
skb_reserve(skb, QRTR_HDR_SIZE);
350+
skb_reserve(skb, QRTR_HDR_MAX_SIZE);
295351
*pkt = skb_put_zero(skb, pkt_len);
296352

297353
return skb;
@@ -720,12 +776,12 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
720776
}
721777

722778
plen = (len + 3) & ~3;
723-
skb = sock_alloc_send_skb(sk, plen + QRTR_HDR_SIZE,
779+
skb = sock_alloc_send_skb(sk, plen + QRTR_HDR_MAX_SIZE,
724780
msg->msg_flags & MSG_DONTWAIT, &rc);
725781
if (!skb)
726782
goto out_node;
727783

728-
skb_reserve(skb, QRTR_HDR_SIZE);
784+
skb_reserve(skb, QRTR_HDR_MAX_SIZE);
729785

730786
rc = memcpy_from_msg(skb_put(skb, len), msg, len);
731787
if (rc) {

0 commit comments

Comments
 (0)