Netdev Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v2 0/2] can: Add CAN_RAW_RECV_OWN_MSGS_ALL socket option
@ 2021-05-04 20:35 Erik Flodin
  2021-05-04 20:35 ` [PATCH v2 1/2] can: add support for filtering own messages only Erik Flodin
  2021-05-04 20:35 ` [PATCH v2 2/2] can: raw: add CAN_RAW_RECV_OWN_MSGS_ALL socket option Erik Flodin
  0 siblings, 2 replies; 4+ messages in thread
From: Erik Flodin @ 2021-05-04 20:35 UTC (permalink / raw)
  To: socketcan, mkl
  Cc: davem, kuba, corbet, linux-can, netdev, linux-doc, Erik Flodin

Add a socket option that works as CAN_RAW_RECV_OWN_MSGS but where reception
of a socket's own frame isn't subject to filtering. This way transmission
confirmation can more easily (or at all if CAN_RAW_JOIN_FILTERS is enabled)
be used in combination with filters.

Changes since v1:
- Rebase on top of can-next/master.

Erik Flodin (2):
  can: add support for filtering own messages only
  can: raw: add CAN_RAW_RECV_OWN_MSGS_ALL socket option

 Documentation/networking/can.rst |   7 +++
 include/linux/can/core.h         |   4 +-
 include/uapi/linux/can/raw.h     |  18 +++---
 net/can/af_can.c                 |  50 ++++++++-------
 net/can/af_can.h                 |   1 +
 net/can/bcm.c                    |   9 ++-
 net/can/gw.c                     |   7 ++-
 net/can/isotp.c                  |   8 +--
 net/can/j1939/main.c             |   4 +-
 net/can/proc.c                   |  11 ++--
 net/can/raw.c                    | 101 +++++++++++++++++++++++++------
 11 files changed, 153 insertions(+), 67 deletions(-)


base-commit: 9d31d2338950293ec19d9b095fbaa9030899dcb4
-- 
2.31.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/2] can: add support for filtering own messages only
  2021-05-04 20:35 [PATCH v2 0/2] can: Add CAN_RAW_RECV_OWN_MSGS_ALL socket option Erik Flodin
@ 2021-05-04 20:35 ` Erik Flodin
  2021-05-05  6:58   ` Oliver Hartkopp
  2021-05-04 20:35 ` [PATCH v2 2/2] can: raw: add CAN_RAW_RECV_OWN_MSGS_ALL socket option Erik Flodin
  1 sibling, 1 reply; 4+ messages in thread
From: Erik Flodin @ 2021-05-04 20:35 UTC (permalink / raw)
  To: socketcan, mkl
  Cc: davem, kuba, corbet, linux-can, netdev, linux-doc, Erik Flodin

Add a new flag to can_rx_register/unregister that, when set, requires
that the received sk_buff's owning socket matches the socket pointer
given when setting the filter. This makes it possible to set a filter
that matches all frames sent on a given socket and nothing else.

Signed-off-by: Erik Flodin <erik@flodin.me>
---
 include/linux/can/core.h |  4 ++--
 net/can/af_can.c         | 50 ++++++++++++++++++++++------------------
 net/can/af_can.h         |  1 +
 net/can/bcm.c            |  9 +++++---
 net/can/gw.c             |  7 +++---
 net/can/isotp.c          |  8 +++----
 net/can/j1939/main.c     |  4 ++--
 net/can/proc.c           | 11 +++++----
 net/can/raw.c            | 10 ++++----
 9 files changed, 58 insertions(+), 46 deletions(-)

diff --git a/include/linux/can/core.h b/include/linux/can/core.h
index 5fb8d0e3f9c1..7ee68128dc10 100644
--- a/include/linux/can/core.h
+++ b/include/linux/can/core.h
@@ -48,12 +48,12 @@ extern int  can_proto_register(const struct can_proto *cp);
 extern void can_proto_unregister(const struct can_proto *cp);
 
 int can_rx_register(struct net *net, struct net_device *dev,
-		    canid_t can_id, canid_t mask,
+		    canid_t can_id, canid_t mask, bool match_sk,
 		    void (*func)(struct sk_buff *, void *),
 		    void *data, char *ident, struct sock *sk);
 
 extern void can_rx_unregister(struct net *net, struct net_device *dev,
-			      canid_t can_id, canid_t mask,
+			      canid_t can_id, canid_t mask, bool match_sk,
 			      void (*func)(struct sk_buff *, void *),
 			      void *data);
 
diff --git a/net/can/af_can.c b/net/can/af_can.c
index cce2af10eb3e..7b639c121653 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -414,6 +414,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
  * @dev: pointer to netdevice (NULL => subscribe from 'all' CAN devices list)
  * @can_id: CAN identifier (see description)
  * @mask: CAN mask (see description)
+ * @match_sk: match socket pointer on received sk_buff (see description)
  * @func: callback function on filter match
  * @data: returned parameter for callback function
  * @ident: string for calling module identification
@@ -428,6 +429,9 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
  *  The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
  *  filter for error message frames (CAN_ERR_FLAG bit set in mask).
  *
+ *  If match_sk is true, the received sk_buff's owning socket must also match
+ *  the given socket pointer.
+ *
  *  The provided pointer to the sk_buff is guaranteed to be valid as long as
  *  the callback function is running. The callback function must *not* free
  *  the given sk_buff while processing it's task. When the given sk_buff is
@@ -440,8 +444,9 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
  *  -ENODEV unknown device
  */
 int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
-		    canid_t mask, void (*func)(struct sk_buff *, void *),
-		    void *data, char *ident, struct sock *sk)
+		    canid_t mask, bool match_sk,
+		    void (*func)(struct sk_buff *, void *), void *data,
+		    char *ident, struct sock *sk)
 {
 	struct receiver *rcv;
 	struct hlist_head *rcv_list;
@@ -468,6 +473,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
 
 	rcv->can_id = can_id;
 	rcv->mask = mask;
+	rcv->match_sk = match_sk;
 	rcv->matches = 0;
 	rcv->func = func;
 	rcv->data = data;
@@ -503,6 +509,7 @@ static void can_rx_delete_receiver(struct rcu_head *rp)
  * @dev: pointer to netdevice (NULL => unsubscribe from 'all' CAN devices list)
  * @can_id: CAN identifier
  * @mask: CAN mask
+ * @match_sk: match socket pointer on received sk_buff
  * @func: callback function on filter match
  * @data: returned parameter for callback function
  *
@@ -510,8 +517,8 @@ static void can_rx_delete_receiver(struct rcu_head *rp)
  *  Removes subscription entry depending on given (subscription) values.
  */
 void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
-		       canid_t mask, void (*func)(struct sk_buff *, void *),
-		       void *data)
+		       canid_t mask, bool match_sk,
+		       void (*func)(struct sk_buff *, void *), void *data)
 {
 	struct receiver *rcv = NULL;
 	struct hlist_head *rcv_list;
@@ -535,7 +542,8 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
 	 */
 	hlist_for_each_entry_rcu(rcv, rcv_list, list) {
 		if (rcv->can_id == can_id && rcv->mask == mask &&
-		    rcv->func == func && rcv->data == data)
+		    rcv->match_sk == match_sk && rcv->func == func &&
+		    rcv->data == data)
 			break;
 	}
 
@@ -546,8 +554,8 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
 	 * a warning here.
 	 */
 	if (!rcv) {
-		pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X\n",
-			DNAME(dev), can_id, mask);
+		pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X%s\n",
+			DNAME(dev), can_id, mask, match_sk ? " (match sk)" : "");
 		goto out;
 	}
 
@@ -569,10 +577,14 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
 }
 EXPORT_SYMBOL(can_rx_unregister);
 
-static inline void deliver(struct sk_buff *skb, struct receiver *rcv)
+static inline int deliver(struct sk_buff *skb, struct receiver *rcv)
 {
-	rcv->func(skb, rcv->data);
-	rcv->matches++;
+	if (!rcv->match_sk || skb->sk == rcv->sk) {
+		rcv->func(skb, rcv->data);
+		rcv->matches++;
+		return 1;
+	}
+	return 0;
 }
 
 static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb)
@@ -589,8 +601,7 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
 		/* check for error message frame entries only */
 		hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ERR], list) {
 			if (can_id & rcv->mask) {
-				deliver(skb, rcv);
-				matches++;
+				matches += deliver(skb, rcv);
 			}
 		}
 		return matches;
@@ -598,23 +609,20 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
 
 	/* check for unfiltered entries */
 	hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ALL], list) {
-		deliver(skb, rcv);
-		matches++;
+		matches += deliver(skb, rcv);
 	}
 
 	/* check for can_id/mask entries */
 	hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_FIL], list) {
 		if ((can_id & rcv->mask) == rcv->can_id) {
-			deliver(skb, rcv);
-			matches++;
+			matches += deliver(skb, rcv);
 		}
 	}
 
 	/* check for inverted can_id/mask entries */
 	hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_INV], list) {
 		if ((can_id & rcv->mask) != rcv->can_id) {
-			deliver(skb, rcv);
-			matches++;
+			matches += deliver(skb, rcv);
 		}
 	}
 
@@ -625,15 +633,13 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
 	if (can_id & CAN_EFF_FLAG) {
 		hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_eff[effhash(can_id)], list) {
 			if (rcv->can_id == can_id) {
-				deliver(skb, rcv);
-				matches++;
+				matches += deliver(skb, rcv);
 			}
 		}
 	} else {
 		can_id &= CAN_SFF_MASK;
 		hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_sff[can_id], list) {
-			deliver(skb, rcv);
-			matches++;
+			matches += deliver(skb, rcv);
 		}
 	}
 
diff --git a/net/can/af_can.h b/net/can/af_can.h
index 7c2d9161e224..ea98b10d93e7 100644
--- a/net/can/af_can.h
+++ b/net/can/af_can.h
@@ -52,6 +52,7 @@ struct receiver {
 	struct hlist_node list;
 	canid_t can_id;
 	canid_t mask;
+	bool match_sk;
 	unsigned long matches;
 	void (*func)(struct sk_buff *skb, void *data);
 	void *data;
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 909b9e684e04..d89dd82c2178 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -729,7 +729,8 @@ static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op)
 {
 	if (op->rx_reg_dev == dev) {
 		can_rx_unregister(dev_net(dev), dev, op->can_id,
-				  REGMASK(op->can_id), bcm_rx_handler, op);
+				  REGMASK(op->can_id), false, bcm_rx_handler,
+				  op);
 
 		/* mark as removed subscription */
 		op->rx_reg_dev = NULL;
@@ -775,6 +776,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
 				can_rx_unregister(sock_net(op->sk), NULL,
 						  op->can_id,
 						  REGMASK(op->can_id),
+						  false,
 						  bcm_rx_handler, op);
 
 			list_del(&op->list);
@@ -1193,6 +1195,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 				err = can_rx_register(sock_net(sk), dev,
 						      op->can_id,
 						      REGMASK(op->can_id),
+						      false,
 						      bcm_rx_handler, op,
 						      "bcm", sk);
 
@@ -1202,7 +1205,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 
 		} else
 			err = can_rx_register(sock_net(sk), NULL, op->can_id,
-					      REGMASK(op->can_id),
+					      REGMASK(op->can_id), false,
 					      bcm_rx_handler, op, "bcm", sk);
 		if (err) {
 			/* this bcm rx op is broken -> remove it */
@@ -1500,7 +1503,7 @@ static int bcm_release(struct socket *sock)
 			}
 		} else
 			can_rx_unregister(net, NULL, op->can_id,
-					  REGMASK(op->can_id),
+					  REGMASK(op->can_id), false,
 					  bcm_rx_handler, op);
 
 		bcm_remove_op(op);
diff --git a/net/can/gw.c b/net/can/gw.c
index ba4124805602..5dbc7b85e0fc 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -567,14 +567,15 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
 static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
 {
 	return can_rx_register(net, gwj->src.dev, gwj->ccgw.filter.can_id,
-			       gwj->ccgw.filter.can_mask, can_can_gw_rcv,
-			       gwj, "gw", NULL);
+			       gwj->ccgw.filter.can_mask, false,
+			       can_can_gw_rcv, gwj, "gw", NULL);
 }
 
 static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj)
 {
 	can_rx_unregister(net, gwj->src.dev, gwj->ccgw.filter.can_id,
-			  gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj);
+			  gwj->ccgw.filter.can_mask, false, can_can_gw_rcv,
+			  gwj);
 }
 
 static int cgw_notifier(struct notifier_block *nb,
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 9f94ad3caee9..44d943bbe0b1 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -1029,7 +1029,7 @@ static int isotp_release(struct socket *sock)
 			if (dev) {
 				can_rx_unregister(net, dev, so->rxid,
 						  SINGLE_MASK(so->rxid),
-						  isotp_rcv, sk);
+						  false, isotp_rcv, sk);
 				dev_put(dev);
 			}
 		}
@@ -1111,7 +1111,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
 	if (do_rx_reg)
 		can_rx_register(net, dev, addr->can_addr.tp.rx_id,
 				SINGLE_MASK(addr->can_addr.tp.rx_id),
-				isotp_rcv, sk, "isotp", sk);
+				false, isotp_rcv, sk, "isotp", sk);
 
 	dev_put(dev);
 
@@ -1122,7 +1122,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
 			if (dev) {
 				can_rx_unregister(net, dev, so->rxid,
 						  SINGLE_MASK(so->rxid),
-						  isotp_rcv, sk);
+						  false, isotp_rcv, sk);
 				dev_put(dev);
 			}
 		}
@@ -1323,7 +1323,7 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg,
 		if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST)))
 			can_rx_unregister(dev_net(dev), dev, so->rxid,
 					  SINGLE_MASK(so->rxid),
-					  isotp_rcv, sk);
+					  false, isotp_rcv, sk);
 
 		so->ifindex = 0;
 		so->bound  = 0;
diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c
index da3a7a7bcff2..466a20c76fb6 100644
--- a/net/can/j1939/main.c
+++ b/net/can/j1939/main.c
@@ -177,7 +177,7 @@ static int j1939_can_rx_register(struct j1939_priv *priv)
 
 	j1939_priv_get(priv);
 	ret = can_rx_register(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
-			      j1939_can_recv, priv, "j1939", NULL);
+			      false, j1939_can_recv, priv, "j1939", NULL);
 	if (ret < 0) {
 		j1939_priv_put(priv);
 		return ret;
@@ -191,7 +191,7 @@ static void j1939_can_rx_unregister(struct j1939_priv *priv)
 	struct net_device *ndev = priv->ndev;
 
 	can_rx_unregister(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
-			  j1939_can_recv, priv);
+			  false, j1939_can_recv, priv);
 
 	j1939_priv_put(priv);
 }
diff --git a/net/can/proc.c b/net/can/proc.c
index d1fe49e6f16d..d312077832a6 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -191,11 +191,12 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
 
 	hlist_for_each_entry_rcu(r, rx_list, list) {
 		char *fmt = (r->can_id & CAN_EFF_FLAG)?
-			"   %-5s  %08x  %08x  %pK  %pK  %8ld  %s\n" :
-			"   %-5s     %03x    %08x  %pK  %pK  %8ld  %s\n";
+			"   %-5s  %08x  %08x   %c   %pK  %pK  %8ld  %s\n" :
+			"   %-5s     %03x    %08x   %c   %pK  %pK  %8ld  %s\n";
 
 		seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
-				r->func, r->data, r->matches, r->ident);
+				r->match_sk ? '*' : ' ', r->func, r->data,
+				r->matches, r->ident);
 	}
 }
 
@@ -206,9 +207,9 @@ static void can_print_recv_banner(struct seq_file *m)
 	 *                 .......          0  tp20
 	 */
 	if (IS_ENABLED(CONFIG_64BIT))
-		seq_puts(m, "  device   can_id   can_mask      function          userdata       matches  ident\n");
+		seq_puts(m, "  device   can_id   can_mask  own      function          userdata       matches  ident\n");
 	else
-		seq_puts(m, "  device   can_id   can_mask  function  userdata   matches  ident\n");
+		seq_puts(m, "  device   can_id   can_mask  own  function  userdata   matches  ident\n");
 }
 
 static int can_stats_proc_show(struct seq_file *m, void *v)
diff --git a/net/can/raw.c b/net/can/raw.c
index 139d9471ddcf..acfbae28d451 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -187,13 +187,13 @@ static int raw_enable_filters(struct net *net, struct net_device *dev,
 
 	for (i = 0; i < count; i++) {
 		err = can_rx_register(net, dev, filter[i].can_id,
-				      filter[i].can_mask,
+				      filter[i].can_mask, false,
 				      raw_rcv, sk, "raw", sk);
 		if (err) {
 			/* clean up successfully registered filters */
 			while (--i >= 0)
 				can_rx_unregister(net, dev, filter[i].can_id,
-						  filter[i].can_mask,
+						  filter[i].can_mask, false,
 						  raw_rcv, sk);
 			break;
 		}
@@ -209,7 +209,7 @@ static int raw_enable_errfilter(struct net *net, struct net_device *dev,
 
 	if (err_mask)
 		err = can_rx_register(net, dev, 0, err_mask | CAN_ERR_FLAG,
-				      raw_rcv, sk, "raw", sk);
+				      false, raw_rcv, sk, "raw", sk);
 
 	return err;
 }
@@ -222,7 +222,7 @@ static void raw_disable_filters(struct net *net, struct net_device *dev,
 
 	for (i = 0; i < count; i++)
 		can_rx_unregister(net, dev, filter[i].can_id,
-				  filter[i].can_mask, raw_rcv, sk);
+				  filter[i].can_mask, false, raw_rcv, sk);
 }
 
 static inline void raw_disable_errfilter(struct net *net,
@@ -233,7 +233,7 @@ static inline void raw_disable_errfilter(struct net *net,
 {
 	if (err_mask)
 		can_rx_unregister(net, dev, 0, err_mask | CAN_ERR_FLAG,
-				  raw_rcv, sk);
+				  false, raw_rcv, sk);
 }
 
 static inline void raw_disable_allfilters(struct net *net,
-- 
2.31.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] can: raw: add CAN_RAW_RECV_OWN_MSGS_ALL socket option
  2021-05-04 20:35 [PATCH v2 0/2] can: Add CAN_RAW_RECV_OWN_MSGS_ALL socket option Erik Flodin
  2021-05-04 20:35 ` [PATCH v2 1/2] can: add support for filtering own messages only Erik Flodin
@ 2021-05-04 20:35 ` Erik Flodin
  1 sibling, 0 replies; 4+ messages in thread
From: Erik Flodin @ 2021-05-04 20:35 UTC (permalink / raw)
  To: socketcan, mkl
  Cc: davem, kuba, corbet, linux-can, netdev, linux-doc, Erik Flodin

CAN_RAW_RECV_OWN_MSGS_ALL works as CAN_RAW_RECV_OWN_MSGS with the
difference that all sent frames are received as no filtering is applied
on the socket's own frames in this case.

Signed-off-by: Erik Flodin <erik@flodin.me>
---
 Documentation/networking/can.rst |  7 +++
 include/uapi/linux/can/raw.h     | 18 ++++---
 net/can/raw.c                    | 91 +++++++++++++++++++++++++++-----
 3 files changed, 95 insertions(+), 21 deletions(-)

diff --git a/Documentation/networking/can.rst b/Documentation/networking/can.rst
index f34cb0e4460e..80c70357cd33 100644
--- a/Documentation/networking/can.rst
+++ b/Documentation/networking/can.rst
@@ -611,6 +611,13 @@ demand:
 Note that reception of a socket's own CAN frames are subject to the same
 filtering as other CAN frames (see :ref:`socketcan-rawfilter`).
 
+RAW socket option CAN_RAW_RECV_OWN_MSGS_ALL
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Identical to CAN_RAW_RECV_OWN_MSGS except that all sent messages are
+received. I.e. reception is not subject to filtering.
+
+
 .. _socketcan-rawfd:
 
 RAW Socket Option CAN_RAW_FD_FRAMES
diff --git a/include/uapi/linux/can/raw.h b/include/uapi/linux/can/raw.h
index 3386aa81fdf2..6e29b2b145e2 100644
--- a/include/uapi/linux/can/raw.h
+++ b/include/uapi/linux/can/raw.h
@@ -53,15 +53,17 @@ enum {
 	SCM_CAN_RAW_ERRQUEUE = 1,
 };
 
-/* for socket options affecting the socket (not the global system) */
-
+/* For socket options affecting the socket (not the global system).
+ * Options default to off unless noted otherwise.
+ */
 enum {
-	CAN_RAW_FILTER = 1,	/* set 0 .. n can_filter(s)          */
-	CAN_RAW_ERR_FILTER,	/* set filter for error frames       */
-	CAN_RAW_LOOPBACK,	/* local loopback (default:on)       */
-	CAN_RAW_RECV_OWN_MSGS,	/* receive my own msgs (default:off) */
-	CAN_RAW_FD_FRAMES,	/* allow CAN FD frames (default:off) */
-	CAN_RAW_JOIN_FILTERS,	/* all filters must match to trigger */
+	CAN_RAW_FILTER = 1,	   /* set 0 .. n can_filter(s)          */
+	CAN_RAW_ERR_FILTER,	   /* set filter for error frames       */
+	CAN_RAW_LOOPBACK,	   /* local loopback (default on)       */
+	CAN_RAW_RECV_OWN_MSGS,	   /* receive my own msgs w/ filtering  */
+	CAN_RAW_FD_FRAMES,	   /* allow CAN FD frames               */
+	CAN_RAW_JOIN_FILTERS,	   /* all filters must match to trigger */
+	CAN_RAW_RECV_OWN_MSGS_ALL, /* receive my own msgs w/o filtering */
 };
 
 #endif /* !_UAPI_CAN_RAW_H */
diff --git a/net/can/raw.c b/net/can/raw.c
index acfbae28d451..79c29942b0be 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -86,6 +86,7 @@ struct raw_sock {
 	struct notifier_block notifier;
 	int loopback;
 	int recv_own_msgs;
+	int recv_own_msgs_all;
 	int fd_frames;
 	int join_filters;
 	int count;                 /* number of active filters */
@@ -122,7 +123,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
 	unsigned int *pflags;
 
 	/* check the received tx sock reference */
-	if (!ro->recv_own_msgs && oskb->sk == sk)
+	if (!ro->recv_own_msgs && !ro->recv_own_msgs_all && oskb->sk == sk)
 		return;
 
 	/* do not pass non-CAN2.0 frames to a legacy socket */
@@ -132,7 +133,8 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
 	/* eliminate multiple filter matches for the same skb */
 	if (this_cpu_ptr(ro->uniq)->skb == oskb &&
 	    this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
-		if (ro->join_filters) {
+		if (ro->join_filters &&
+		    (!ro->recv_own_msgs_all || oskb->sk != sk)) {
 			this_cpu_inc(ro->uniq->join_rx_count);
 			/* drop frame until all enabled filters matched */
 			if (this_cpu_ptr(ro->uniq)->join_rx_count < ro->count)
@@ -145,8 +147,10 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
 		this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
 		this_cpu_ptr(ro->uniq)->join_rx_count = 1;
 		/* drop first frame to check all enabled filters? */
-		if (ro->join_filters && ro->count > 1)
+		if (ro->join_filters && ro->count > 1 &&
+		    (!ro->recv_own_msgs_all || oskb->sk != sk)) {
 			return;
+		}
 	}
 
 	/* clone the given skb to be able to enqueue it into the rcv queue */
@@ -214,6 +218,18 @@ static int raw_enable_errfilter(struct net *net, struct net_device *dev,
 	return err;
 }
 
+static int raw_enable_ownfilter(struct net *net, struct net_device *dev,
+				struct sock *sk, bool recv_own_msgs_all)
+{
+	int err = 0;
+
+	if (recv_own_msgs_all)
+		err = can_rx_register(net, dev, 0, MASK_ALL, true, raw_rcv,
+				      sk, "raw", sk);
+
+	return err;
+}
+
 static void raw_disable_filters(struct net *net, struct net_device *dev,
 				struct sock *sk, struct can_filter *filter,
 				int count)
@@ -236,6 +252,13 @@ static inline void raw_disable_errfilter(struct net *net,
 				  false, raw_rcv, sk);
 }
 
+static void raw_disable_ownfilter(struct net *net, struct net_device *dev,
+				  struct sock *sk, bool recv_own_msgs_all)
+{
+	if (recv_own_msgs_all)
+		can_rx_unregister(net, dev, 0, MASK_ALL, true, raw_rcv, sk);
+}
+
 static inline void raw_disable_allfilters(struct net *net,
 					  struct net_device *dev,
 					  struct sock *sk)
@@ -244,6 +267,7 @@ static inline void raw_disable_allfilters(struct net *net,
 
 	raw_disable_filters(net, dev, sk, ro->filter, ro->count);
 	raw_disable_errfilter(net, dev, sk, ro->err_mask);
+	raw_disable_ownfilter(net, dev, sk, ro->recv_own_msgs_all);
 }
 
 static int raw_enable_allfilters(struct net *net, struct net_device *dev,
@@ -253,13 +277,19 @@ static int raw_enable_allfilters(struct net *net, struct net_device *dev,
 	int err;
 
 	err = raw_enable_filters(net, dev, sk, ro->filter, ro->count);
-	if (!err) {
-		err = raw_enable_errfilter(net, dev, sk, ro->err_mask);
-		if (err)
-			raw_disable_filters(net, dev, sk, ro->filter,
-					    ro->count);
-	}
+	if (err)
+		goto out;
+	err = raw_enable_errfilter(net, dev, sk, ro->err_mask);
+	if (err)
+		goto out_disable;
+	err = raw_enable_ownfilter(net, dev, sk, ro->recv_own_msgs_all);
+	if (!err)
+		goto out;
 
+	raw_disable_errfilter(net, dev, sk, ro->err_mask);
+out_disable:
+	raw_disable_filters(net, dev, sk, ro->filter, ro->count);
+out:
 	return err;
 }
 
@@ -323,10 +353,11 @@ static int raw_init(struct sock *sk)
 	ro->count            = 1;
 
 	/* set default loopback behaviour */
-	ro->loopback         = 1;
-	ro->recv_own_msgs    = 0;
-	ro->fd_frames        = 0;
-	ro->join_filters     = 0;
+	ro->loopback          = 1;
+	ro->recv_own_msgs     = 0;
+	ro->recv_own_msgs_all = 0;
+	ro->fd_frames         = 0;
+	ro->join_filters      = 0;
 
 	/* alloc_percpu provides zero'ed memory */
 	ro->uniq = alloc_percpu(struct uniqframe);
@@ -495,6 +526,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
 	can_err_mask_t err_mask = 0;
 	int count = 0;
 	int err = 0;
+	int old_val;
 
 	if (level != SOL_CAN_RAW)
 		return -EINVAL;
@@ -639,6 +671,33 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
 
 		break;
 
+	case CAN_RAW_RECV_OWN_MSGS_ALL:
+		if (optlen != sizeof(ro->recv_own_msgs_all))
+			return -EINVAL;
+
+		old_val = ro->recv_own_msgs_all;
+		if (copy_from_sockptr(&ro->recv_own_msgs_all, optval, optlen))
+			return -EFAULT;
+
+		lock_sock(sk);
+
+		if (ro->bound && ro->ifindex)
+			dev = dev_get_by_index(sock_net(sk), ro->ifindex);
+
+		if (ro->bound) {
+			if (old_val && !ro->recv_own_msgs_all)
+				raw_disable_ownfilter(sock_net(sk), dev, sk, true);
+			else if (!old_val && ro->recv_own_msgs_all)
+				err = raw_enable_ownfilter(sock_net(sk), dev, sk, true);
+		}
+
+		if (dev)
+			dev_put(dev);
+
+		release_sock(sk);
+
+		break;
+
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -718,6 +777,12 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
 		val = &ro->join_filters;
 		break;
 
+	case CAN_RAW_RECV_OWN_MSGS_ALL:
+		if (len > sizeof(int))
+			len = sizeof(int);
+		val = &ro->recv_own_msgs_all;
+		break;
+
 	default:
 		return -ENOPROTOOPT;
 	}
-- 
2.31.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 1/2] can: add support for filtering own messages only
  2021-05-04 20:35 ` [PATCH v2 1/2] can: add support for filtering own messages only Erik Flodin
@ 2021-05-05  6:58   ` Oliver Hartkopp
  0 siblings, 0 replies; 4+ messages in thread
From: Oliver Hartkopp @ 2021-05-05  6:58 UTC (permalink / raw)
  To: Erik Flodin, mkl; +Cc: davem, kuba, corbet, linux-can, netdev, linux-doc

Hi Erik,

IMO putting linux-can@vger.kernel.org in CC would be sufficient in this 
stage of discussion.

On 04.05.21 22:35, Erik Flodin wrote:
> Add a new flag to can_rx_register/unregister that, when set, requires
> that the received sk_buff's owning socket matches the socket pointer
> given when setting the filter. This makes it possible to set a filter
> that matches all frames sent on a given socket and nothing else.

This is a pretty simple requirement and you are touching almost every 
CAN network layer file.

 From this description I would suggest a two-liner to be added in raw.c

diff --git a/net/can/raw.c b/net/can/raw.c
index 139d9471ddcf..8c6371a0c8a6 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -123,10 +123,14 @@ static void raw_rcv(struct sk_buff *oskb, void *data)

         /* check the received tx sock reference */
         if (!ro->recv_own_msgs && oskb->sk == sk)
                 return;

+       /* check the received tx sock reference */
+       if (ro->recv_only_own_msgs && oskb->sk != sk)
+               return;
+
         /* do not pass non-CAN2.0 frames to a legacy socket */
         if (!ro->fd_frames && oskb->len != CAN_MTU)
                 return;

         /* eliminate multiple filter matches for the same skb */


And then add CAN_RAW_RECV_ONLY_OWN_MSGS accordingly.

Wouldn't that already match your requirements?

Best regards,
Oliver

ps. please reduce the CC receipient list before answering, thanks.

> 
> Signed-off-by: Erik Flodin <erik@flodin.me>
> ---
>   include/linux/can/core.h |  4 ++--
>   net/can/af_can.c         | 50 ++++++++++++++++++++++------------------
>   net/can/af_can.h         |  1 +
>   net/can/bcm.c            |  9 +++++---
>   net/can/gw.c             |  7 +++---
>   net/can/isotp.c          |  8 +++----
>   net/can/j1939/main.c     |  4 ++--
>   net/can/proc.c           | 11 +++++----
>   net/can/raw.c            | 10 ++++----
>   9 files changed, 58 insertions(+), 46 deletions(-)
> 
> diff --git a/include/linux/can/core.h b/include/linux/can/core.h
> index 5fb8d0e3f9c1..7ee68128dc10 100644
> --- a/include/linux/can/core.h
> +++ b/include/linux/can/core.h
> @@ -48,12 +48,12 @@ extern int  can_proto_register(const struct can_proto *cp);
>   extern void can_proto_unregister(const struct can_proto *cp);
>   
>   int can_rx_register(struct net *net, struct net_device *dev,
> -		    canid_t can_id, canid_t mask,
> +		    canid_t can_id, canid_t mask, bool match_sk,
>   		    void (*func)(struct sk_buff *, void *),
>   		    void *data, char *ident, struct sock *sk);
>   
>   extern void can_rx_unregister(struct net *net, struct net_device *dev,
> -			      canid_t can_id, canid_t mask,
> +			      canid_t can_id, canid_t mask, bool match_sk,
>   			      void (*func)(struct sk_buff *, void *),
>   			      void *data);
>   
> diff --git a/net/can/af_can.c b/net/can/af_can.c
> index cce2af10eb3e..7b639c121653 100644
> --- a/net/can/af_can.c
> +++ b/net/can/af_can.c
> @@ -414,6 +414,7 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
>    * @dev: pointer to netdevice (NULL => subscribe from 'all' CAN devices list)
>    * @can_id: CAN identifier (see description)
>    * @mask: CAN mask (see description)
> + * @match_sk: match socket pointer on received sk_buff (see description)
>    * @func: callback function on filter match
>    * @data: returned parameter for callback function
>    * @ident: string for calling module identification
> @@ -428,6 +429,9 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
>    *  The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
>    *  filter for error message frames (CAN_ERR_FLAG bit set in mask).
>    *
> + *  If match_sk is true, the received sk_buff's owning socket must also match
> + *  the given socket pointer.
> + *
>    *  The provided pointer to the sk_buff is guaranteed to be valid as long as
>    *  the callback function is running. The callback function must *not* free
>    *  the given sk_buff while processing it's task. When the given sk_buff is
> @@ -440,8 +444,9 @@ static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask,
>    *  -ENODEV unknown device
>    */
>   int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
> -		    canid_t mask, void (*func)(struct sk_buff *, void *),
> -		    void *data, char *ident, struct sock *sk)
> +		    canid_t mask, bool match_sk,
> +		    void (*func)(struct sk_buff *, void *), void *data,
> +		    char *ident, struct sock *sk)
>   {
>   	struct receiver *rcv;
>   	struct hlist_head *rcv_list;
> @@ -468,6 +473,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
>   
>   	rcv->can_id = can_id;
>   	rcv->mask = mask;
> +	rcv->match_sk = match_sk;
>   	rcv->matches = 0;
>   	rcv->func = func;
>   	rcv->data = data;
> @@ -503,6 +509,7 @@ static void can_rx_delete_receiver(struct rcu_head *rp)
>    * @dev: pointer to netdevice (NULL => unsubscribe from 'all' CAN devices list)
>    * @can_id: CAN identifier
>    * @mask: CAN mask
> + * @match_sk: match socket pointer on received sk_buff
>    * @func: callback function on filter match
>    * @data: returned parameter for callback function
>    *
> @@ -510,8 +517,8 @@ static void can_rx_delete_receiver(struct rcu_head *rp)
>    *  Removes subscription entry depending on given (subscription) values.
>    */
>   void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
> -		       canid_t mask, void (*func)(struct sk_buff *, void *),
> -		       void *data)
> +		       canid_t mask, bool match_sk,
> +		       void (*func)(struct sk_buff *, void *), void *data)
>   {
>   	struct receiver *rcv = NULL;
>   	struct hlist_head *rcv_list;
> @@ -535,7 +542,8 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
>   	 */
>   	hlist_for_each_entry_rcu(rcv, rcv_list, list) {
>   		if (rcv->can_id == can_id && rcv->mask == mask &&
> -		    rcv->func == func && rcv->data == data)
> +		    rcv->match_sk == match_sk && rcv->func == func &&
> +		    rcv->data == data)
>   			break;
>   	}
>   
> @@ -546,8 +554,8 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
>   	 * a warning here.
>   	 */
>   	if (!rcv) {
> -		pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X\n",
> -			DNAME(dev), can_id, mask);
> +		pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X%s\n",
> +			DNAME(dev), can_id, mask, match_sk ? " (match sk)" : "");
>   		goto out;
>   	}
>   
> @@ -569,10 +577,14 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,
>   }
>   EXPORT_SYMBOL(can_rx_unregister);
>   
> -static inline void deliver(struct sk_buff *skb, struct receiver *rcv)
> +static inline int deliver(struct sk_buff *skb, struct receiver *rcv)
>   {
> -	rcv->func(skb, rcv->data);
> -	rcv->matches++;
> +	if (!rcv->match_sk || skb->sk == rcv->sk) {
> +		rcv->func(skb, rcv->data);
> +		rcv->matches++;
> +		return 1;
> +	}
> +	return 0;
>   }
>   
>   static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buff *skb)
> @@ -589,8 +601,7 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
>   		/* check for error message frame entries only */
>   		hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ERR], list) {
>   			if (can_id & rcv->mask) {
> -				deliver(skb, rcv);
> -				matches++;
> +				matches += deliver(skb, rcv);
>   			}
>   		}
>   		return matches;
> @@ -598,23 +609,20 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
>   
>   	/* check for unfiltered entries */
>   	hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ALL], list) {
> -		deliver(skb, rcv);
> -		matches++;
> +		matches += deliver(skb, rcv);
>   	}
>   
>   	/* check for can_id/mask entries */
>   	hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_FIL], list) {
>   		if ((can_id & rcv->mask) == rcv->can_id) {
> -			deliver(skb, rcv);
> -			matches++;
> +			matches += deliver(skb, rcv);
>   		}
>   	}
>   
>   	/* check for inverted can_id/mask entries */
>   	hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_INV], list) {
>   		if ((can_id & rcv->mask) != rcv->can_id) {
> -			deliver(skb, rcv);
> -			matches++;
> +			matches += deliver(skb, rcv);
>   		}
>   	}
>   
> @@ -625,15 +633,13 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
>   	if (can_id & CAN_EFF_FLAG) {
>   		hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_eff[effhash(can_id)], list) {
>   			if (rcv->can_id == can_id) {
> -				deliver(skb, rcv);
> -				matches++;
> +				matches += deliver(skb, rcv);
>   			}
>   		}
>   	} else {
>   		can_id &= CAN_SFF_MASK;
>   		hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_sff[can_id], list) {
> -			deliver(skb, rcv);
> -			matches++;
> +			matches += deliver(skb, rcv);
>   		}
>   	}
>   
> diff --git a/net/can/af_can.h b/net/can/af_can.h
> index 7c2d9161e224..ea98b10d93e7 100644
> --- a/net/can/af_can.h
> +++ b/net/can/af_can.h
> @@ -52,6 +52,7 @@ struct receiver {
>   	struct hlist_node list;
>   	canid_t can_id;
>   	canid_t mask;
> +	bool match_sk;
>   	unsigned long matches;
>   	void (*func)(struct sk_buff *skb, void *data);
>   	void *data;
> diff --git a/net/can/bcm.c b/net/can/bcm.c
> index 909b9e684e04..d89dd82c2178 100644
> --- a/net/can/bcm.c
> +++ b/net/can/bcm.c
> @@ -729,7 +729,8 @@ static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op)
>   {
>   	if (op->rx_reg_dev == dev) {
>   		can_rx_unregister(dev_net(dev), dev, op->can_id,
> -				  REGMASK(op->can_id), bcm_rx_handler, op);
> +				  REGMASK(op->can_id), false, bcm_rx_handler,
> +				  op);
>   
>   		/* mark as removed subscription */
>   		op->rx_reg_dev = NULL;
> @@ -775,6 +776,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
>   				can_rx_unregister(sock_net(op->sk), NULL,
>   						  op->can_id,
>   						  REGMASK(op->can_id),
> +						  false,
>   						  bcm_rx_handler, op);
>   
>   			list_del(&op->list);
> @@ -1193,6 +1195,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
>   				err = can_rx_register(sock_net(sk), dev,
>   						      op->can_id,
>   						      REGMASK(op->can_id),
> +						      false,
>   						      bcm_rx_handler, op,
>   						      "bcm", sk);
>   
> @@ -1202,7 +1205,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
>   
>   		} else
>   			err = can_rx_register(sock_net(sk), NULL, op->can_id,
> -					      REGMASK(op->can_id),
> +					      REGMASK(op->can_id), false,
>   					      bcm_rx_handler, op, "bcm", sk);
>   		if (err) {
>   			/* this bcm rx op is broken -> remove it */
> @@ -1500,7 +1503,7 @@ static int bcm_release(struct socket *sock)
>   			}
>   		} else
>   			can_rx_unregister(net, NULL, op->can_id,
> -					  REGMASK(op->can_id),
> +					  REGMASK(op->can_id), false,
>   					  bcm_rx_handler, op);
>   
>   		bcm_remove_op(op);
> diff --git a/net/can/gw.c b/net/can/gw.c
> index ba4124805602..5dbc7b85e0fc 100644
> --- a/net/can/gw.c
> +++ b/net/can/gw.c
> @@ -567,14 +567,15 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
>   static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
>   {
>   	return can_rx_register(net, gwj->src.dev, gwj->ccgw.filter.can_id,
> -			       gwj->ccgw.filter.can_mask, can_can_gw_rcv,
> -			       gwj, "gw", NULL);
> +			       gwj->ccgw.filter.can_mask, false,
> +			       can_can_gw_rcv, gwj, "gw", NULL);
>   }
>   
>   static inline void cgw_unregister_filter(struct net *net, struct cgw_job *gwj)
>   {
>   	can_rx_unregister(net, gwj->src.dev, gwj->ccgw.filter.can_id,
> -			  gwj->ccgw.filter.can_mask, can_can_gw_rcv, gwj);
> +			  gwj->ccgw.filter.can_mask, false, can_can_gw_rcv,
> +			  gwj);
>   }
>   
>   static int cgw_notifier(struct notifier_block *nb,
> diff --git a/net/can/isotp.c b/net/can/isotp.c
> index 9f94ad3caee9..44d943bbe0b1 100644
> --- a/net/can/isotp.c
> +++ b/net/can/isotp.c
> @@ -1029,7 +1029,7 @@ static int isotp_release(struct socket *sock)
>   			if (dev) {
>   				can_rx_unregister(net, dev, so->rxid,
>   						  SINGLE_MASK(so->rxid),
> -						  isotp_rcv, sk);
> +						  false, isotp_rcv, sk);
>   				dev_put(dev);
>   			}
>   		}
> @@ -1111,7 +1111,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
>   	if (do_rx_reg)
>   		can_rx_register(net, dev, addr->can_addr.tp.rx_id,
>   				SINGLE_MASK(addr->can_addr.tp.rx_id),
> -				isotp_rcv, sk, "isotp", sk);
> +				false, isotp_rcv, sk, "isotp", sk);
>   
>   	dev_put(dev);
>   
> @@ -1122,7 +1122,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
>   			if (dev) {
>   				can_rx_unregister(net, dev, so->rxid,
>   						  SINGLE_MASK(so->rxid),
> -						  isotp_rcv, sk);
> +						  false, isotp_rcv, sk);
>   				dev_put(dev);
>   			}
>   		}
> @@ -1323,7 +1323,7 @@ static int isotp_notifier(struct notifier_block *nb, unsigned long msg,
>   		if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST)))
>   			can_rx_unregister(dev_net(dev), dev, so->rxid,
>   					  SINGLE_MASK(so->rxid),
> -					  isotp_rcv, sk);
> +					  false, isotp_rcv, sk);
>   
>   		so->ifindex = 0;
>   		so->bound  = 0;
> diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c
> index da3a7a7bcff2..466a20c76fb6 100644
> --- a/net/can/j1939/main.c
> +++ b/net/can/j1939/main.c
> @@ -177,7 +177,7 @@ static int j1939_can_rx_register(struct j1939_priv *priv)
>   
>   	j1939_priv_get(priv);
>   	ret = can_rx_register(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
> -			      j1939_can_recv, priv, "j1939", NULL);
> +			      false, j1939_can_recv, priv, "j1939", NULL);
>   	if (ret < 0) {
>   		j1939_priv_put(priv);
>   		return ret;
> @@ -191,7 +191,7 @@ static void j1939_can_rx_unregister(struct j1939_priv *priv)
>   	struct net_device *ndev = priv->ndev;
>   
>   	can_rx_unregister(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
> -			  j1939_can_recv, priv);
> +			  false, j1939_can_recv, priv);
>   
>   	j1939_priv_put(priv);
>   }
> diff --git a/net/can/proc.c b/net/can/proc.c
> index d1fe49e6f16d..d312077832a6 100644
> --- a/net/can/proc.c
> +++ b/net/can/proc.c
> @@ -191,11 +191,12 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
>   
>   	hlist_for_each_entry_rcu(r, rx_list, list) {
>   		char *fmt = (r->can_id & CAN_EFF_FLAG)?
> -			"   %-5s  %08x  %08x  %pK  %pK  %8ld  %s\n" :
> -			"   %-5s     %03x    %08x  %pK  %pK  %8ld  %s\n";
> +			"   %-5s  %08x  %08x   %c   %pK  %pK  %8ld  %s\n" :
> +			"   %-5s     %03x    %08x   %c   %pK  %pK  %8ld  %s\n";
>   
>   		seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
> -				r->func, r->data, r->matches, r->ident);
> +				r->match_sk ? '*' : ' ', r->func, r->data,
> +				r->matches, r->ident);
>   	}
>   }
>   
> @@ -206,9 +207,9 @@ static void can_print_recv_banner(struct seq_file *m)
>   	 *                 .......          0  tp20
>   	 */
>   	if (IS_ENABLED(CONFIG_64BIT))
> -		seq_puts(m, "  device   can_id   can_mask      function          userdata       matches  ident\n");
> +		seq_puts(m, "  device   can_id   can_mask  own      function          userdata       matches  ident\n");
>   	else
> -		seq_puts(m, "  device   can_id   can_mask  function  userdata   matches  ident\n");
> +		seq_puts(m, "  device   can_id   can_mask  own  function  userdata   matches  ident\n");
>   }
>   
>   static int can_stats_proc_show(struct seq_file *m, void *v)
> diff --git a/net/can/raw.c b/net/can/raw.c
> index 139d9471ddcf..acfbae28d451 100644
> --- a/net/can/raw.c
> +++ b/net/can/raw.c
> @@ -187,13 +187,13 @@ static int raw_enable_filters(struct net *net, struct net_device *dev,
>   
>   	for (i = 0; i < count; i++) {
>   		err = can_rx_register(net, dev, filter[i].can_id,
> -				      filter[i].can_mask,
> +				      filter[i].can_mask, false,
>   				      raw_rcv, sk, "raw", sk);
>   		if (err) {
>   			/* clean up successfully registered filters */
>   			while (--i >= 0)
>   				can_rx_unregister(net, dev, filter[i].can_id,
> -						  filter[i].can_mask,
> +						  filter[i].can_mask, false,
>   						  raw_rcv, sk);
>   			break;
>   		}
> @@ -209,7 +209,7 @@ static int raw_enable_errfilter(struct net *net, struct net_device *dev,
>   
>   	if (err_mask)
>   		err = can_rx_register(net, dev, 0, err_mask | CAN_ERR_FLAG,
> -				      raw_rcv, sk, "raw", sk);
> +				      false, raw_rcv, sk, "raw", sk);
>   
>   	return err;
>   }
> @@ -222,7 +222,7 @@ static void raw_disable_filters(struct net *net, struct net_device *dev,
>   
>   	for (i = 0; i < count; i++)
>   		can_rx_unregister(net, dev, filter[i].can_id,
> -				  filter[i].can_mask, raw_rcv, sk);
> +				  filter[i].can_mask, false, raw_rcv, sk);
>   }
>   
>   static inline void raw_disable_errfilter(struct net *net,
> @@ -233,7 +233,7 @@ static inline void raw_disable_errfilter(struct net *net,
>   {
>   	if (err_mask)
>   		can_rx_unregister(net, dev, 0, err_mask | CAN_ERR_FLAG,
> -				  raw_rcv, sk);
> +				  false, raw_rcv, sk);
>   }
>   
>   static inline void raw_disable_allfilters(struct net *net,
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, back to index

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-04 20:35 [PATCH v2 0/2] can: Add CAN_RAW_RECV_OWN_MSGS_ALL socket option Erik Flodin
2021-05-04 20:35 ` [PATCH v2 1/2] can: add support for filtering own messages only Erik Flodin
2021-05-05  6:58   ` Oliver Hartkopp
2021-05-04 20:35 ` [PATCH v2 2/2] can: raw: add CAN_RAW_RECV_OWN_MSGS_ALL socket option Erik Flodin

Netdev Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/netdev/0 netdev/git/0.git
	git clone --mirror https://lore.kernel.org/netdev/1 netdev/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 netdev netdev/ https://lore.kernel.org/netdev \
		netdev@vger.kernel.org
	public-inbox-index netdev

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.netdev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git