Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/bouyer-socketcan]: src/sys/netcan Use PACKET_TAG_SO to store the sender'...
details: https://anonhg.NetBSD.org/src/rev/cf36359cdadb
branches: bouyer-socketcan
changeset: 820808:cf36359cdadb
user: bouyer <bouyer%NetBSD.org@localhost>
date: Mon Jan 16 18:03:38 2017 +0000
description:
Use PACKET_TAG_SO to store the sender's struct socket pointer, and use
it to implement socket options CAN_RAW_LOOPBACK and CAN_RAW_RECV_OWN_MSGS.
diffstat:
sys/netcan/can.c | 145 ++++++++++++++++++++++++++++++++++++++++++++---
sys/netcan/can.h | 11 +-
sys/netcan/can_pcb.h | 12 ++-
sys/netcan/can_proto.c | 5 +-
sys/netcan/can_var.h | 4 +-
sys/netcan/if_canloop.c | 10 ++-
6 files changed, 161 insertions(+), 26 deletions(-)
diffs (truncated from 373 to 300 lines):
diff -r c5876f0347ec -r cf36359cdadb sys/netcan/can.c
--- a/sys/netcan/can.c Mon Jan 16 18:02:00 2017 +0000
+++ b/sys/netcan/can.c Mon Jan 16 18:03:38 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: can.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */
+/* $NetBSD: can.c,v 1.1.2.2 2017/01/16 18:03:38 bouyer Exp $ */
/*-
* Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -30,12 +30,13 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.2 2017/01/16 18:03:38 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/ioctl.h>
+#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/errno.h>
#include <sys/socket.h>
@@ -119,25 +120,35 @@
{
struct ifnet *ifp;
int error = 0;
+ struct m_tag *sotag;
- if (canp == 0) {
+ if (canp == NULL) {
printf("can_output: no pcb\n");
error = EINVAL;
- goto done;
+ return error;
}
ifp = canp->canp_ifp;
if (ifp == 0) {
error = EDESTADDRREQ;
- goto done;
+ goto bad;
}
+ sotag = m_tag_get(PACKET_TAG_SO, sizeof(struct socket *), PR_NOWAIT);
+ if (sotag == NULL) {
+ ifp->if_oerrors++;
+ error = ENOMEM;
+ goto bad;
+ }
+ *(struct socket **)(sotag + 1) = canp->canp_socket;
+ m_tag_prepend(m, sotag);
+
if (m->m_len <= ifp->if_mtu) {
can_output_cnt++;
error = (*ifp->if_output)(ifp, m, NULL, 0);
- goto done;
- } else error = EMSGSIZE;
-
+ return error;
+ } else
+ error = EMSGSIZE;
+bad:
m_freem(m);
-done:
return (error);
}
@@ -180,6 +191,9 @@
struct sockaddr_can from;
struct canpcb *canp;
+ struct m_tag *sotag;
+ struct socket *so;
+ struct canpcb *sender_canp;
mutex_enter(softnet_lock);
for (;;) {
@@ -187,9 +201,22 @@
IF_DEQUEUE(&canintrq, m);
IFQ_UNLOCK(&canintrq);
- if (m == 0) /* no more queued packets */
+ if (m == NULL) /* no more queued packets */
break;
+ sotag = m_tag_find(m, PACKET_TAG_SO, NULL);
+ if (sotag) {
+ so = *(struct socket **)(sotag + 1);
+ sender_canp = sotocanpcb(so);
+ m_tag_delete(m, sotag);
+ /* if the sender doesn't want loopback, don't do it */
+ if (sender_canp->canp_flags & CANP_NO_LOOPBACK) {
+ m_freem(m);
+ continue;
+ }
+ } else {
+ sender_canp = NULL;
+ }
memset(&from, 0, sizeof(struct sockaddr_can));
rcv_ifindex = m->m_pkthdr.rcvif_index;
#if 0
@@ -201,10 +228,17 @@
TAILQ_FOREACH(canp, &cbtable.canpt_queue, canp_queue) {
struct mbuf *mc;
+
+ /* don't loop back to sockets on other interfaces */
if (canp->canp_ifp != NULL &&
canp->canp_ifp->if_index != rcv_ifindex) {
continue;
}
+ /* don't loop back to myself if I don't want it */
+ if (canp == sender_canp &&
+ (canp->canp_flags & CANP_RECEIVE_OWN) == 0)
+ continue;
+
if (TAILQ_NEXT(canp, canp_queue) != NULL) {
/*
* we can't be sure we won't need
@@ -653,6 +687,97 @@
}
#endif
+static int
+can_raw_getop(struct canpcb *canp, struct sockopt *sopt)
+{
+ int optval = 0;
+ int error;
+
+ switch (sopt->sopt_name) {
+ case CAN_RAW_LOOPBACK:
+ optval = (canp->canp_flags & CANP_NO_LOOPBACK) ? 0 : 1;
+ error = sockopt_set(sopt, &optval, sizeof(optval));
+ break;
+ case CAN_RAW_RECV_OWN_MSGS:
+ optval = (canp->canp_flags & CANP_RECEIVE_OWN) ? 1 : 0;
+ error = sockopt_set(sopt, &optval, sizeof(optval));
+ break;
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ return error;
+}
+
+static int
+can_raw_setop(struct canpcb *canp, struct sockopt *sopt)
+{
+ int optval = 0;
+ int error;
+
+ switch (sopt->sopt_name) {
+ case CAN_RAW_LOOPBACK:
+ error = sockopt_getint(sopt, &optval);
+ if (error == 0) {
+ if (optval) {
+ canp->canp_flags &= ~CANP_NO_LOOPBACK;
+ } else {
+ canp->canp_flags |= CANP_NO_LOOPBACK;
+ }
+ }
+ break;
+ case CAN_RAW_RECV_OWN_MSGS:
+ error = sockopt_getint(sopt, &optval);
+ if (error == 0) {
+ if (optval) {
+ canp->canp_flags |= CANP_RECEIVE_OWN;
+ } else {
+ canp->canp_flags &= ~CANP_RECEIVE_OWN;
+ }
+ }
+ break;
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ return error;
+}
+
+/*
+ * Called by getsockopt and setsockopt.
+ *
+ */
+int
+can_ctloutput(int op, struct socket *so, struct sockopt *sopt)
+{
+ struct canpcb *canp;
+ int error;
+ int s;
+
+ if (so->so_proto->pr_domain->dom_family != PF_CAN)
+ return EAFNOSUPPORT;
+
+ if (sopt->sopt_level != SOL_CAN_RAW)
+ return EINVAL;
+
+ s = splsoftnet();
+ canp = sotocanpcb(so);
+ if (canp == NULL) {
+ splx(s);
+ return ECONNRESET;
+ }
+
+ if (op == PRCO_SETOPT) {
+ error = can_raw_setop(canp, sopt);
+ } else if (op == PRCO_GETOPT) {
+ error = can_raw_getop(canp, sopt);
+ } else {
+ error = EINVAL;
+ }
+ splx(s);
+ return error;
+}
+
PR_WRAP_USRREQS(can)
#define can_attach can_attach_wrapper
#define can_detach can_detach_wrapper
diff -r c5876f0347ec -r cf36359cdadb sys/netcan/can.h
--- a/sys/netcan/can.h Mon Jan 16 18:02:00 2017 +0000
+++ b/sys/netcan/can.h Mon Jan 16 18:03:38 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: can.h,v 1.1.2.2 2017/01/15 21:01:34 bouyer Exp $ */
+/* $NetBSD: can.h,v 1.1.2.3 2017/01/16 18:03:38 bouyer Exp $ */
/*-
* Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -77,8 +77,6 @@
#define CAN_RAW 1 /* RAW sockets */
#define CAN_NPROTO 2
-#define SOL_CAN_BASE 100
-
/*
* Socket address, CAN style
*/
@@ -94,11 +92,14 @@
};
/*
- * Options for use with [gs]etsockopt
+ * Options for use with [gs]etsockopt for raw sockets
* First word of comment is data type; bool is stored in int.
*/
+#define SOL_CAN_RAW CAN_RAW
-#define CAN_RAW_FILTER 1 /* struct can_filter: set filter */
+#define CAN_RAW_FILTER 1 /* struct can_filter: set filter */
+#define CAN_RAW_LOOPBACK 4 /* bool: loopback to local sockets (default:on) */
+#define CAN_RAW_RECV_OWN_MSGS 5 /* bool: receive my own msgs (default:off) */
/*
* CAN ID based filter
diff -r c5876f0347ec -r cf36359cdadb sys/netcan/can_pcb.h
--- a/sys/netcan/can_pcb.h Mon Jan 16 18:02:00 2017 +0000
+++ b/sys/netcan/can_pcb.h Mon Jan 16 18:03:38 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: can_pcb.h,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */
+/* $NetBSD: can_pcb.h,v 1.1.2.2 2017/01/16 18:03:38 bouyer Exp $ */
/*-
* Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -49,8 +49,9 @@
LIST_ENTRY(canpcb) canp_lhash;
TAILQ_ENTRY(canpcb) canp_queue;
int canp_state;
+ int canp_flags;
struct socket *canp_socket; /* back pointer to socket */
- struct ifnet *canp_ifp;
+ struct ifnet *canp_ifp; /* interface this socket is bound to */
struct canpcbtable *canp_table;
};
@@ -68,12 +69,15 @@
u_long canpt_connecthash;
};
-/* states in inp_state: */
+/* states in canp_state: */
#define CANP_ATTACHED 0
#define CANP_BOUND 1
#define CANP_CONNECTED 2
-/* flags in inp_flags: */
+/* flags in canp_flags: */
+#define CANP_NO_LOOPBACK 0x0001 /* local loopback disabled */
+#define CANP_RECEIVE_OWN 0x0002 /* receive own message */
+
#define sotocanpcb(so) ((struct canpcb *)(so)->so_pcb)
diff -r c5876f0347ec -r cf36359cdadb sys/netcan/can_proto.c
--- a/sys/netcan/can_proto.c Mon Jan 16 18:02:00 2017 +0000
+++ b/sys/netcan/can_proto.c Mon Jan 16 18:03:38 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: can_proto.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */
+/* $NetBSD: can_proto.c,v 1.1.2.2 2017/01/16 18:03:38 bouyer Exp $ */
/*-
* Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
Home |
Main Index |
Thread Index |
Old Index