Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/bouyer-socketcan]: src Implement CAN_RAW_FILTER socket option, and add t...



details:   https://anonhg.NetBSD.org/src/rev/46c81238cd24
branches:  bouyer-socketcan
changeset: 820821:46c81238cd24
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sun Feb 05 10:56:12 2017 +0000

description:
Implement CAN_RAW_FILTER socket option, and add tests for it.

diffstat:

 sys/netcan/can.c            |   28 +-
 sys/netcan/can_pcb.c        |   66 +++++-
 sys/netcan/can_pcb.h        |    9 +-
 tests/net/can/Makefile      |    9 +-
 tests/net/can/t_canfilter.c |  537 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 633 insertions(+), 16 deletions(-)

diffs (truncated from 807 to 300 lines):

diff -r d6d3dfd21081 -r 46c81238cd24 sys/netcan/can.c
--- a/sys/netcan/can.c  Sat Feb 04 22:26:16 2017 +0000
+++ b/sys/netcan/can.c  Sun Feb 05 10:56:12 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: can.c,v 1.1.2.2 2017/01/16 18:03:38 bouyer Exp $       */
+/*     $NetBSD: can.c,v 1.1.2.3 2017/02/05 10:56:12 bouyer Exp $       */
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.2 2017/01/16 18:03:38 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.3 2017/02/05 10:56:12 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -204,6 +204,9 @@
                if (m == NULL)  /* no more queued packets */
                        break;
 
+#if 0
+               m_claim(m, &can_rx_mowner);
+#endif
                sotag = m_tag_find(m, PACKET_TAG_SO, NULL);
                if (sotag) {
                        so = *(struct socket **)(sotag + 1);
@@ -219,9 +222,6 @@
                }
                memset(&from, 0, sizeof(struct sockaddr_can));
                rcv_ifindex = m->m_pkthdr.rcvif_index;
-#if 0
-               m_claim(m, &can_rx_mowner);
-#endif
                from.can_ifindex = rcv_ifindex;
                from.can_len = sizeof(struct sockaddr_can);
                from.can_family = AF_CAN;
@@ -239,6 +239,10 @@
                            (canp->canp_flags & CANP_RECEIVE_OWN) == 0)
                                continue;
 
+                       /* skip if the accept filter doen't match this pkt */
+                       if (!can_pcbfilter(canp, m))
+                               continue;
+
                        if (TAILQ_NEXT(canp, canp_queue) != NULL) {
                                /*
                                 * we can't be sure we won't need 
@@ -274,7 +278,6 @@
 static int
 can_attach(struct socket *so, int proto)
 {
-       /*struct canpcb *canp;*/
        int error;
 
        KASSERT(sotocanpcb(so) == NULL);
@@ -298,7 +301,6 @@
        if (error) {
                return error;
        }
-       /*canp = sotocanpcb(so);*/
        KASSERT(solocked(so));
 
        return error;
@@ -702,6 +704,10 @@
                optval = (canp->canp_flags & CANP_RECEIVE_OWN) ? 1 : 0;
                error = sockopt_set(sopt, &optval, sizeof(optval));
                break;
+       case CAN_RAW_FILTER:
+               error = sockopt_set(sopt, canp->canp_filters,
+                   sizeof(struct can_filter) * canp->canp_nfilters);
+               break;
        default:
                error = ENOPROTOOPT;
                break;
@@ -736,6 +742,14 @@
                        }
                }
                break;
+       case CAN_RAW_FILTER:
+               {
+               int nfilters = sopt->sopt_size / sizeof(struct can_filter);
+               if (sopt->sopt_size % sizeof(struct can_filter) != 0)
+                       return EINVAL;
+               error = can_pcbsetfilter(canp, sopt->sopt_data, nfilters);
+               break;
+               }
        default:
                error = ENOPROTOOPT;
                break;
diff -r d6d3dfd21081 -r 46c81238cd24 sys/netcan/can_pcb.c
--- a/sys/netcan/can_pcb.c      Sat Feb 04 22:26:16 2017 +0000
+++ b/sys/netcan/can_pcb.c      Sun Feb 05 10:56:12 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: can_pcb.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $   */
+/*     $NetBSD: can_pcb.c,v 1.1.2.2 2017/02/05 10:56:12 bouyer Exp $   */
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -30,11 +30,12 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: can_pcb.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: can_pcb.c,v 1.1.2.2 2017/02/05 10:56:12 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/mbuf.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
@@ -84,16 +85,27 @@
 {
        struct canpcbtable *table = v;
        struct canpcb *canp;
+       struct can_filter *can_init_filter;
        int s;
 
+       can_init_filter = kmem_alloc(sizeof(struct can_filter), KM_NOSLEEP);
+       if (can_init_filter == NULL)
+               return (ENOBUFS);
+       can_init_filter->can_id = 0;
+       can_init_filter->can_mask = 0; /* accept all by default */
+
        s = splnet();
        canp = pool_get(&canpcb_pool, PR_NOWAIT);
        splx(s);
-       if (canp == NULL)
+       if (canp == NULL) {
+               kmem_free(can_init_filter, sizeof(struct can_filter));
                return (ENOBUFS);
+       }
        memset(canp, 0, sizeof(*canp));
        canp->canp_table = table;
        canp->canp_socket = so;
+       canp->canp_filters = can_init_filter;
+       canp->canp_nfilters = 1;
 
        so->so_pcb = canp;
        s = splnet();
@@ -169,6 +181,7 @@
        TAILQ_REMOVE(&canp->canp_table->canpt_queue, canp, canp_queue);
        splx(s);
        sofree(so); /* sofree drops the lock */
+       can_pcbsetfilter(canp, NULL, 0);
        pool_put(&canpcb_pool, canp);
        mutex_enter(softnet_lock);
 }
@@ -183,6 +196,32 @@
        scan->can_ifindex = canp->canp_ifp->if_index;
 }
 
+int
+can_pcbsetfilter(struct canpcb *canp, struct can_filter *fp, int nfilters)
+{
+
+       struct can_filter *newf;
+
+       if (nfilters > 0) {
+               newf =
+                   kmem_alloc(sizeof(struct can_filter) * nfilters, KM_SLEEP);
+               if (newf == NULL)
+                       return ENOMEM;
+               memcpy(newf, fp, sizeof(struct can_filter) * nfilters);
+       } else {
+               newf = NULL;
+       }
+       if (canp->canp_filters != NULL) {
+               kmem_free(canp->canp_filters,
+                   sizeof(struct can_filter) * canp->canp_nfilters);
+       }
+       canp->canp_filters = newf;
+       canp->canp_nfilters = nfilters;
+       return 0;
+}
+
+
+
 #if 0
 /*
  * Pass some notification to all connections of a protocol
@@ -281,3 +320,24 @@
 
        canp->canp_state = state;
 }
+
+/*
+ * check mbuf against socket accept filter.
+ * returns true if mbuf is accepted, false otherwise
+ */
+bool
+can_pcbfilter(struct canpcb *canp, struct mbuf *m)
+{
+       int i;
+       struct can_frame *fmp;
+       struct can_filter *fip;
+
+       fmp = mtod(m, struct can_frame *);
+       for (i = 0; i < canp->canp_nfilters; i++) {
+               fip = &canp->canp_filters[i];
+               if ((fmp->can_id & fip->can_mask) == fip->can_id)
+                       return true;
+       }
+       /* no match */
+       return false;
+}
diff -r d6d3dfd21081 -r 46c81238cd24 sys/netcan/can_pcb.h
--- a/sys/netcan/can_pcb.h      Sat Feb 04 22:26:16 2017 +0000
+++ b/sys/netcan/can_pcb.h      Sun Feb 05 10:56:12 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: can_pcb.h,v 1.1.2.2 2017/01/16 18:03:38 bouyer Exp $   */
+/*     $NetBSD: can_pcb.h,v 1.1.2.3 2017/02/05 10:56:12 bouyer Exp $   */
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -52,13 +52,14 @@
        int             canp_flags;
        struct          socket *canp_socket;    /* back pointer to socket */
        struct          ifnet *canp_ifp; /* interface this socket is bound to */
+
        struct          canpcbtable *canp_table;
+       struct          can_filter *canp_filters; /* filter array */
+       int             canp_nfilters; /* size of canp_filters */
 };
 
 LIST_HEAD(canpcbhead, canpcb);
 
-#define canp_faddr     canp_dst.scan_addr
-
 TAILQ_HEAD(canpcbqueue, canpcb);
 
 struct canpcbtable {
@@ -97,6 +98,8 @@
 void   can_pcbpurgeif(struct canpcbtable *, struct ifnet *);
 void   can_pcbstate(struct canpcb *, int);
 void   can_setsockaddr(struct canpcb *, struct sockaddr_can *);
+int    can_pcbsetfilter(struct canpcb *, struct can_filter *, int);
+bool   can_pcbfilter(struct canpcb *, struct mbuf *);
 #endif
 
 #endif /* _NETCAN_CAN_PCB_H_ */
diff -r d6d3dfd21081 -r 46c81238cd24 tests/net/can/Makefile
--- a/tests/net/can/Makefile    Sat Feb 04 22:26:16 2017 +0000
+++ b/tests/net/can/Makefile    Sun Feb 05 10:56:12 2017 +0000
@@ -1,12 +1,15 @@
-# $NetBSD: Makefile,v 1.1.2.2 2017/02/04 22:26:16 bouyer Exp $
+# $NetBSD: Makefile,v 1.1.2.3 2017/02/05 10:56:12 bouyer Exp $
 #
 
 .include <bsd.own.mk>
 
 TESTSDIR=      ${TESTSBASE}/net/can
 
-TESTS_C=       t_can
-SRCS.t_can=    t_can.c h_canutils.c
+TESTS_C=       t_can t_canfilter
+
+SRCS.t_can=            t_can.c h_canutils.c
+
+SRCS.t_canfilter=      t_canfilter.c h_canutils.c
 
 # XXX we don't use INET here, but we need rumpnet_netinet anyway:
 # common code in if.c is compiled with -DINET and will dereference ip_pktq,
diff -r d6d3dfd21081 -r 46c81238cd24 tests/net/can/t_canfilter.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/net/can/t_canfilter.c       Sun Feb 05 10:56:12 2017 +0000
@@ -0,0 +1,537 @@
+/*     $NetBSD: t_canfilter.c,v 1.1.2.1 2017/02/05 10:56:12 bouyer Exp $       */
+
+/*-
+ * Copyright (c) 2017 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Manuel Bouyer
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.



Home | Main Index | Thread Index | Old Index