From patchwork Wed Oct 11 06:45:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 115507 Delivered-To: patch@linaro.org Received: by 10.140.22.163 with SMTP id 32csp408984qgn; Tue, 10 Oct 2017 23:45:59 -0700 (PDT) X-Received: by 10.98.50.66 with SMTP id y63mr15919365pfy.155.1507704359882; Tue, 10 Oct 2017 23:45:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1507704359; cv=none; d=google.com; s=arc-20160816; b=TwFh8nrVty87RbrNkC/L6IP+zGeJCOHl2MWpU4SidyyciSyc8BwYDbynPimwsg9joB cMLVhsDq/7ECCF0LY/HBDnkzPIxuSaAa7wU9J3v2iOyIcFhnxB5iH7giAaSU2BKHzzO3 Cwadyljw1gruhBIkKGKZbzJQ/R0GjrlXCYAipu8kIoJNS0wb/oYyOygrv4CYL/e7v0bd Zd595eFA9vRGssmv0cIU0m14o2DK1ODDj/9ZW8J8Ek6Y2JguyKrYpuwiIW3CTFoSEsTQ EYvysIszYuLUAfsk7K4HmtV6bVkI7YIAFgCK+ksTdXfQ7IEWd5zvfXTS0jAbph6iYc4k 9eMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=uI30fVoZYQc4HVDfnlhM+XiZkFYD0NAdoBJXGsFHK6E=; b=VMjPqUPmslcmkGUzfDvYpVu/aEztZNYpLaMLs/nSdWVsQomOmq0w2w0jgeT9FA6GcI BdWRVH8t7s300+VV7eAADVVSSKXfX2FRMk3HMRvKNY42zuEWLUt+LR4i3aZUWr/n7Vb3 CmF5mBk50HC0pdB2Lj7McsPfGg52KrdcBVSh43TwI1e1aqfH/z3e1vyTUQCYTTNxlrdG 2A37qUfzvDVLIBOzY8If9gaUYMcbbx9yIVQH4AIQN2wGYgFXK+DQ8aPsetlp0P/bt7Rv hodfBKBOdcIXWNQgg8mash6M41UhmR7eAJRdmJg5lnd/no12sUMzoZKt2wGuOUdbf32O nkDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=eTIgJ7vb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b68si7217001pfg.366.2017.10.10.23.45.59; Tue, 10 Oct 2017 23:45:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=eTIgJ7vb; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757109AbdJKGpj (ORCPT + 26 others); Wed, 11 Oct 2017 02:45:39 -0400 Received: from mail-pf0-f181.google.com ([209.85.192.181]:50592 "EHLO mail-pf0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756998AbdJKGpg (ORCPT ); Wed, 11 Oct 2017 02:45:36 -0400 Received: by mail-pf0-f181.google.com with SMTP id m63so648370pfk.7 for ; Tue, 10 Oct 2017 23:45:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uI30fVoZYQc4HVDfnlhM+XiZkFYD0NAdoBJXGsFHK6E=; b=eTIgJ7vbDUOpQYK6ud3AveUdkMOmlHLuES+S+Qq8jzoL6G6hD8GcoggkEVQQ8ttc2k tbNiqSOPoD443uJY4t0j1HblQXShOy+kpTzF6uzg8YJ1b68CXCqzljl5DfGZrd9J8gRS WUFrh2zwTKIz/Jo1KcmtDyCmQsxpxYQ6YItPw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uI30fVoZYQc4HVDfnlhM+XiZkFYD0NAdoBJXGsFHK6E=; b=FnpQj8/byFAisRMvfqi6Kx8Afn0JrGIcRBEr5WgZ8cDGhjsJVljs6tZ3GjMl8QZNac FD/B6EBIAYhEIeD3E7kyUreebPb2tALkESkEc71GoQ5J8d8X/w9N2sIHICRdO/OqPNxA F4lMkbPpJZVKsazk8Cpu5seP5BndfNJyRA84+JAoD1D2yNFHm7bFpCAk1E5vTso29TDG vxflsptc8Ng9jMJyAY5IvSF1TK5LBA+bfAUPqcGi4Swu+KCk+C7W3sxbQz8iRU979BMl 78t3o3aYIfTN1YGVUqP2pVJoC45f80/PjcAprIjmeMV8XhIMM/vgaz8VIikYDX+mOLAo 7dxg== X-Gm-Message-State: AMCzsaUl5a7z34BsUZoVCzVPrZdAxaqfYiFq05uilbH2eUpd4twbLZ/V TRGl1jP+cx594+db1llXYBhXfR75NpU= X-Google-Smtp-Source: AOwi7QC626oh/5hWBmRZAAUL2WUtLYqu0BAlAemAkYeVFb5o/GApR1gFDjehmntLwspONt74pOn9bA== X-Received: by 10.84.131.36 with SMTP id 33mr14675611pld.100.1507704335868; Tue, 10 Oct 2017 23:45:35 -0700 (PDT) Received: from localhost.localdomain (ip68-111-217-79.sd.sd.cox.net. [68.111.217.79]) by smtp.gmail.com with ESMTPSA id l79sm411779pfb.33.2017.10.10.23.45.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 10 Oct 2017 23:45:35 -0700 (PDT) From: Bjorn Andersson To: "David S. Miller" Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Chris Lew Subject: [PATCH v2 7/7] net: qrtr: Support decoding incoming v2 packets Date: Tue, 10 Oct 2017 23:45:23 -0700 Message-Id: <20171011064523.7902-8-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20171011064523.7902-1-bjorn.andersson@linaro.org> References: <20171011064523.7902-1-bjorn.andersson@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.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 --- Changes since v1: - Dropped __packed from struct qrtr_hdr_v2 net/qrtr/qrtr.c | 132 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 38 deletions(-) -- 2.12.0 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) {