From patchwork Thu Sep 7 06:03:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 111859 Delivered-To: patch@linaro.org Received: by 10.140.94.239 with SMTP id g102csp357337qge; Wed, 6 Sep 2017 23:04:21 -0700 (PDT) X-Received: by 10.84.224.136 with SMTP id s8mr1821395plj.324.1504764261329; Wed, 06 Sep 2017 23:04:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1504764261; cv=none; d=google.com; s=arc-20160816; b=bU+8TFGszDYvGRTEYT8DTpp5vBvlry1VixLBdYqDTPjfW8WO4cEH6coGjbXQp3N/Zu nkE7V3rx0mlmjksHy4qd3HC0tiERbl5wryiCZZ4YD/9ZEC7SMPfM4E7LF71UcFtaAEYd 3edLObOWLbr2AG2FG7uQbfylly6ahi+nVYm/QRHXnUKiZnSihMgR1e36dKyQ+hxKQSlj f7/uXztylncdRkCef9AQF4L75X9dR9wMMk0BWCDOiml2EHt9BQrsQZRSGobRDlK25eBj 2wc2mXYEKJwztEm5KH/Ku2KM4YI1gvWHPq6BDmn2DyrQy35aXpBxJkNd81+dn6tbggpM +LJg== 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=StanxJdbaw1SNc4T2/YT3g2/HEJBj5sy7ikfCMlZTNw=; b=UbgTqyVb4sz6hYlWkOEaLQALsHwomsW5iCoHscfWGTWNjvfGW0y08w2Ljt+CelPPyX BYKRHe294x/kASAgcJOAwRWvrCu85CMRgkQAB/q7G+UbH76GUiQ5JLLyjhESP6FIUqPZ 8zRoaJlucDazjyIQ/GJ/NS4J2Jq8f4JBtJ1eHw+DuatdUNAsSBbM7dfl15Z/ecEEQ7XU e7tOSPVsVH41m//9m3QvG6agu9duOwz1gcePm6TfoHHLdPSBuBbgehszQazhe6F0r7Fr Fr55tOyZ6ui0+d78s28VUt1GIll65ytJulin36QO6UpZIRNXg0SH6a39JvRNBnTN5WgK L22Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Lf1+CbSb; 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 q1si1383547plb.133.2017.09.06.23.04.21; Wed, 06 Sep 2017 23:04:21 -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=Lf1+CbSb; 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 S1754125AbdIGGDq (ORCPT + 26 others); Thu, 7 Sep 2017 02:03:46 -0400 Received: from mail-pf0-f176.google.com ([209.85.192.176]:33129 "EHLO mail-pf0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754029AbdIGGDm (ORCPT ); Thu, 7 Sep 2017 02:03:42 -0400 Received: by mail-pf0-f176.google.com with SMTP id y68so16335939pfd.0 for ; Wed, 06 Sep 2017 23:03:42 -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=StanxJdbaw1SNc4T2/YT3g2/HEJBj5sy7ikfCMlZTNw=; b=Lf1+CbSbMvWwAa6s9a/9JeEdmICv4g9F2ZIBa/CyTnl/9Q6/IyLTGtsZg7m8tbYeLS vFN5s50xjhtle3skj/tsQHz3eTQaJVDNDsjTl/Z8QNj93rC/LDRe5Q1QMOH4TKLjJwyM M1b5nSWdGN7DAM4gTIzcn71F/K3veEf7+b5oY= 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=StanxJdbaw1SNc4T2/YT3g2/HEJBj5sy7ikfCMlZTNw=; b=refWvlFK1GmhkorRrSKNlRU582QV8hVt5XLkfVEbjqyIwEC9pJ1pjdn2x+uejWOKw5 MyGUUKe33XeAnWXjxbgc53z06kvKoqbNZiiwJ9O319fQcLdiMxDQRYysuFK59gjRsL7+ sc1SrwRLn42nQ9JiIoYFOmIRTYLAkDrlg5X2vUeF717UcnTFB8bFPYdQABbBOfyRJXiS r7eb6S80cpBUso+Our+GJ8Jq7YIfn3rh7O4Qcn2rNIdJ5vXGTzPb5riDbD3TU7FYQlYM ZPrqae84AI7e9WQ3zruSf06VDbC2PSWBsbKTFkxPoMqwGec4wlcD6t+CEkD2dPLHZqIC Mhfg== X-Gm-Message-State: AHPjjUgI44hltnjHDVybpPFnhbwew2F4+7xa1GISXg1+9HoPXCNhTO+y O6c6z2LPK7Fz/+x9 X-Google-Smtp-Source: ADKCNb6N6HdHxpv+QeCttxF0zvIOjbD2Vv0on5Jyebhvj7XLPoeiSFeRjsdNmfGfcBzgEKKxrDYvvg== X-Received: by 10.98.13.81 with SMTP id v78mr1609609pfi.61.1504764221625; Wed, 06 Sep 2017 23:03:41 -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 s1sm2186650pfk.27.2017.09.06.23.03.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 06 Sep 2017 23:03:41 -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 7/7] net: qrtr: Support decoding incoming v2 packets Date: Wed, 6 Sep 2017 23:03:29 -0700 Message-Id: <20170907060329.32402-8-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170907060329.32402-1-bjorn.andersson@linaro.org> References: <20170907060329.32402-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 --- 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 5042999756ce..5f397fa1c109 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; +} __packed; + +#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) {