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