20
20
21
21
#include "qrtr.h"
22
22
23
- #define QRTR_PROTO_VER 1
23
+ #define QRTR_PROTO_VER_1 1
24
+ #define QRTR_PROTO_VER_2 3
24
25
25
26
/* auto-bind range */
26
27
#define QRTR_MIN_EPH_SOCKET 0x4000
27
28
#define QRTR_MAX_EPH_SOCKET 0x7fff
28
29
29
30
/**
30
- * struct qrtr_hdr - (I|R)PCrouter packet header
31
+ * struct qrtr_hdr_v1 - (I|R)PCrouter packet header version 1
31
32
* @version: protocol version
32
33
* @type: packet type; one of QRTR_TYPE_*
33
34
* @src_node_id: source node
37
38
* @dst_node_id: destination node
38
39
* @dst_port_id: destination port
39
40
*/
40
- struct qrtr_hdr {
41
+ struct qrtr_hdr_v1 {
41
42
__le32 version ;
42
43
__le32 type ;
43
44
__le32 src_node_id ;
@@ -48,6 +49,32 @@ struct qrtr_hdr {
48
49
__le32 dst_port_id ;
49
50
} __packed ;
50
51
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
+
51
78
struct qrtr_cb {
52
79
u32 src_node ;
53
80
u32 src_port ;
@@ -58,7 +85,8 @@ struct qrtr_cb {
58
85
u8 confirm_rx ;
59
86
};
60
87
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))
62
90
63
91
struct qrtr_sock {
64
92
/* WARNING: sk must be the first member */
@@ -154,12 +182,12 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
154
182
int type , struct sockaddr_qrtr * from ,
155
183
struct sockaddr_qrtr * to )
156
184
{
157
- struct qrtr_hdr * hdr ;
185
+ struct qrtr_hdr_v1 * hdr ;
158
186
size_t len = skb -> len ;
159
187
int rc = - ENODEV ;
160
188
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 );
163
191
hdr -> type = cpu_to_le32 (type );
164
192
hdr -> src_node_id = cpu_to_le32 (from -> sq_node );
165
193
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)
224
252
int qrtr_endpoint_post (struct qrtr_endpoint * ep , const void * data , size_t len )
225
253
{
226
254
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 ;
228
257
struct sk_buff * skb ;
229
258
struct qrtr_cb * cb ;
230
- unsigned int psize ;
231
259
unsigned int size ;
232
- unsigned int type ;
233
260
unsigned int ver ;
234
- unsigned int dst ;
261
+ size_t hdrlen ;
235
262
236
- if (len < QRTR_HDR_SIZE || len & 3 )
263
+ if (len & 3 )
237
264
return - EINVAL ;
238
265
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 ;
243
269
244
- psize = (size + 3 ) & ~ 3 ;
270
+ cb = (struct qrtr_cb * ) skb -> cb ;
245
271
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 ;
248
274
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 );
251
279
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 );
254
286
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
+ }
258
311
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 ;
266
314
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 );
268
319
269
320
skb_queue_tail (& node -> rx_queue , skb );
270
321
schedule_work (& node -> work );
271
322
272
323
return 0 ;
324
+
325
+ err :
326
+ kfree_skb (skb );
327
+ return - EINVAL ;
328
+
273
329
}
274
330
EXPORT_SYMBOL_GPL (qrtr_endpoint_post );
275
331
@@ -287,11 +343,11 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt)
287
343
const int pkt_len = sizeof (struct qrtr_ctrl_pkt );
288
344
struct sk_buff * skb ;
289
345
290
- skb = alloc_skb (QRTR_HDR_SIZE + pkt_len , GFP_KERNEL );
346
+ skb = alloc_skb (QRTR_HDR_MAX_SIZE + pkt_len , GFP_KERNEL );
291
347
if (!skb )
292
348
return NULL ;
293
349
294
- skb_reserve (skb , QRTR_HDR_SIZE );
350
+ skb_reserve (skb , QRTR_HDR_MAX_SIZE );
295
351
* pkt = skb_put_zero (skb , pkt_len );
296
352
297
353
return skb ;
@@ -720,12 +776,12 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
720
776
}
721
777
722
778
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 ,
724
780
msg -> msg_flags & MSG_DONTWAIT , & rc );
725
781
if (!skb )
726
782
goto out_node ;
727
783
728
- skb_reserve (skb , QRTR_HDR_SIZE );
784
+ skb_reserve (skb , QRTR_HDR_MAX_SIZE );
729
785
730
786
rc = memcpy_from_msg (skb_put (skb , len ), msg , len );
731
787
if (rc ) {
0 commit comments