Module Name: src Committed By: bouyer Date: Sun Jan 15 20:27:34 UTC 2017
Modified Files: src/sys [bouyer-socketcan]: Makefile src/sys/conf [bouyer-socketcan]: files src/sys/net [bouyer-socketcan]: netisr.h netisr_dispatch.h src/sys/rump/include/opt [bouyer-socketcan]: opt_rumpkernel.h src/sys/rump/include/rump [bouyer-socketcan]: rumpdefs.h src/sys/rump/net [bouyer-socketcan]: Makefile.rumpnetcomp src/sys/sys [bouyer-socketcan]: socket.h Added Files: src/sys/netcan [bouyer-socketcan]: Makefile can.c can.h can_pcb.c can_pcb.h can_proto.c can_var.h files.netcan if_canloop.c src/sys/rump/net/lib/libnetcan [bouyer-socketcan]: Makefile NETCAN.ioconf netcan_component.c Log Message: Initial commit of a CAN socket layer, compatible with linux SoccketCAN (but incomplete). Based on work from Robert Swindells. To generate a diff of this commit: cvs rdiff -u -r1.79 -r1.79.22.1 src/sys/Makefile cvs rdiff -u -r1.1168 -r1.1168.2.1 src/sys/conf/files cvs rdiff -u -r1.44 -r1.44.4.1 src/sys/net/netisr.h cvs rdiff -u -r1.18 -r1.18.12.1 src/sys/net/netisr_dispatch.h cvs rdiff -u -r0 -r1.1.2.1 src/sys/netcan/Makefile src/sys/netcan/can.c \ src/sys/netcan/can.h src/sys/netcan/can_pcb.c src/sys/netcan/can_pcb.h \ src/sys/netcan/can_proto.c src/sys/netcan/can_var.h \ src/sys/netcan/files.netcan src/sys/netcan/if_canloop.c cvs rdiff -u -r1.5 -r1.5.4.1 src/sys/rump/include/opt/opt_rumpkernel.h cvs rdiff -u -r1.36 -r1.36.4.1 src/sys/rump/include/rump/rumpdefs.h cvs rdiff -u -r1.16 -r1.16.2.1 src/sys/rump/net/Makefile.rumpnetcomp cvs rdiff -u -r0 -r1.1.2.1 src/sys/rump/net/lib/libnetcan/Makefile \ src/sys/rump/net/lib/libnetcan/NETCAN.ioconf \ src/sys/rump/net/lib/libnetcan/netcan_component.c cvs rdiff -u -r1.120 -r1.120.2.1 src/sys/sys/socket.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/Makefile diff -u src/sys/Makefile:1.79 src/sys/Makefile:1.79.22.1 --- src/sys/Makefile:1.79 Fri Mar 1 18:25:27 2013 +++ src/sys/Makefile Sun Jan 15 20:27:33 2017 @@ -1,9 +1,9 @@ -# $NetBSD: Makefile,v 1.79 2013/03/01 18:25:27 joerg Exp $ +# $NetBSD: Makefile,v 1.79.22.1 2017/01/15 20:27:33 bouyer Exp $ .include <bsd.own.mk> SUBDIR= altq arch compat dev fs miscfs \ - net net80211 netatalk netbt netipsec netinet netinet6 \ + net net80211 netatalk netbt netcan netipsec netinet netinet6 \ netisdn netkey netmpls netnatm netsmb \ nfs opencrypto sys ufs uvm Index: src/sys/conf/files diff -u src/sys/conf/files:1.1168 src/sys/conf/files:1.1168.2.1 --- src/sys/conf/files:1.1168 Mon Dec 26 23:12:33 2016 +++ src/sys/conf/files Sun Jan 15 20:27:33 2017 @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.1168 2016/12/26 23:12:33 pgoyette Exp $ +# $NetBSD: files,v 1.1168.2.1 2017/01/15 20:27:33 bouyer Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 version 20150846 @@ -229,6 +229,7 @@ file net/bpfjit.c sljit & bpfjit include "net80211/files.net80211" include "netatalk/files.netatalk" include "netbt/files.netbt" +include "netcan/files.netcan" include "netinet/files.netinet" include "netinet6/files.netinet6" include "netipsec/files.netipsec" @@ -1435,6 +1436,7 @@ defpseudo stf: ifnet defpseudodev tap: ifnet, ether, arp defpseudo carp: ifnet, ether, arp defpseudodev etherip: ifnet, ether, arp +defpseudo canloop: ifnet defpseudo sequencer defpseudo clockctl Index: src/sys/net/netisr.h diff -u src/sys/net/netisr.h:1.44 src/sys/net/netisr.h:1.44.4.1 --- src/sys/net/netisr.h:1.44 Mon May 25 08:29:01 2015 +++ src/sys/net/netisr.h Sun Jan 15 20:27:33 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: netisr.h,v 1.44 2015/05/25 08:29:01 ozaki-r Exp $ */ +/* $NetBSD: netisr.h,v 1.44.4.1 2017/01/15 20:27:33 bouyer Exp $ */ /* * Copyright (c) 1980, 1986, 1989, 1993 @@ -53,6 +53,7 @@ #include "opt_atalk.h" #include "opt_mpls.h" #include "opt_natm.h" +#include "opt_can.h" #include "arp.h" #endif /* defined(_KERNEL_OPT) */ @@ -90,6 +91,10 @@ #ifdef NETATALK #include <netatalk/at_extern.h> #endif +#ifdef CAN +#include <netcan/can.h> +#include <netcan/can_var.h> +#endif #endif /* !defined(_LOCORE) */ #endif /* defined(_KERNEL) */ @@ -109,6 +114,7 @@ #define NETISR_NATM 27 /* same as AF_NATM */ #define NETISR_ARP 28 /* same as AF_ARP */ #define NETISR_MPLS 33 /* same as AF_MPLS */ +#define NETISR_CAN 35 /* same as AF_CAN */ #define NETISR_MAX AF_MAX #if !defined(_LOCORE) && defined(_KERNEL) Index: src/sys/net/netisr_dispatch.h diff -u src/sys/net/netisr_dispatch.h:1.18 src/sys/net/netisr_dispatch.h:1.18.12.1 --- src/sys/net/netisr_dispatch.h:1.18 Thu Jun 5 23:48:16 2014 +++ src/sys/net/netisr_dispatch.h Sun Jan 15 20:27:33 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: netisr_dispatch.h,v 1.18 2014/06/05 23:48:16 rmind Exp $ */ +/* $NetBSD: netisr_dispatch.h,v 1.18.12.1 2017/01/15 20:27:33 bouyer Exp $ */ #ifndef _NET_NETISR_DISPATCH_H_ #define _NET_NETISR_DISPATCH_H_ @@ -41,5 +41,8 @@ #ifdef NATM DONETISR(NETISR_NATM,natmintr); #endif +#ifdef CAN + DONETISR(NETISR_CAN,canintr); +#endif #endif /* !_NET_NETISR_DISPATCH_H_ */ Index: src/sys/rump/include/opt/opt_rumpkernel.h diff -u src/sys/rump/include/opt/opt_rumpkernel.h:1.5 src/sys/rump/include/opt/opt_rumpkernel.h:1.5.4.1 --- src/sys/rump/include/opt/opt_rumpkernel.h:1.5 Fri Apr 15 01:35:26 2016 +++ src/sys/rump/include/opt/opt_rumpkernel.h Sun Jan 15 20:27:33 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: opt_rumpkernel.h,v 1.5 2016/04/15 01:35:26 ozaki-r Exp $ */ +/* $NetBSD: opt_rumpkernel.h,v 1.5.4.1 2017/01/15 20:27:33 bouyer Exp $ */ #ifndef __NetBSD__ #define __NetBSD__ @@ -22,6 +22,8 @@ #define MPLS 1 +#define CAN 1 + #define SOSEND_NO_LOAN #undef PIPE_SOCKETPAIR /* would need uipc_usrreq.c */ Index: src/sys/rump/include/rump/rumpdefs.h diff -u src/sys/rump/include/rump/rumpdefs.h:1.36 src/sys/rump/include/rump/rumpdefs.h:1.36.4.1 --- src/sys/rump/include/rump/rumpdefs.h:1.36 Tue Feb 2 01:15:58 2016 +++ src/sys/rump/include/rump/rumpdefs.h Sun Jan 15 20:27:33 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpdefs.h,v 1.36 2016/02/02 01:15:58 pooka Exp $ */ +/* $NetBSD: rumpdefs.h,v 1.36.4.1 2017/01/15 20:27:33 bouyer Exp $ */ /* * AUTOMATICALLY GENERATED. DO NOT EDIT. @@ -240,7 +240,8 @@ enum rump_vtype { RUMP_VNON, RUMP_VREG, #define RUMP_AF_IEEE80211 32 #define RUMP_AF_MPLS 33 #define RUMP_AF_ROUTE 34 -#define RUMP_AF_MAX 35 +#define RUMP_AF_CAN 35 +#define RUMP_AF_MAX 36 #define RUMP_PF_UNSPEC RUMP_AF_UNSPEC #define RUMP_PF_LOCAL RUMP_AF_LOCAL #define RUMP_PF_UNIX RUMP_PF_LOCAL @@ -277,6 +278,7 @@ enum rump_vtype { RUMP_VNON, RUMP_VREG, #define RUMP_PF_BLUETOOTH RUMP_AF_BLUETOOTH #define RUMP_PF_MPLS RUMP_AF_MPLS #define RUMP_PF_ROUTE RUMP_AF_ROUTE +#define RUMP_PF_CAN RUMP_AF_CAN #define RUMP_PF_MAX RUMP_AF_MAX #define RUMP_SO_DEBUG 0x0001 #define RUMP_SO_ACCEPTCONN 0x0002 Index: src/sys/rump/net/Makefile.rumpnetcomp diff -u src/sys/rump/net/Makefile.rumpnetcomp:1.16 src/sys/rump/net/Makefile.rumpnetcomp:1.16.2.1 --- src/sys/rump/net/Makefile.rumpnetcomp:1.16 Sat Nov 26 03:17:58 2016 +++ src/sys/rump/net/Makefile.rumpnetcomp Sun Jan 15 20:27:34 2017 @@ -1,9 +1,9 @@ -# $NetBSD: Makefile.rumpnetcomp,v 1.16 2016/11/26 03:17:58 ozaki-r Exp $ +# $NetBSD: Makefile.rumpnetcomp,v 1.16.2.1 2017/01/15 20:27:34 bouyer Exp $ # .include <bsd.own.mk> -RUMPNETCOMP= agr bridge net net80211 netbt netinet netinet6 +RUMPNETCOMP= agr bridge net net80211 netbt netcan netinet netinet6 RUMPNETCOMP+= gif netmpls npf local pppoe shmif tap tun vlan .if ${MKSLJIT} != "no" || make(rumpdescribe) Index: src/sys/sys/socket.h diff -u src/sys/sys/socket.h:1.120 src/sys/sys/socket.h:1.120.2.1 --- src/sys/sys/socket.h:1.120 Wed Sep 21 10:50:23 2016 +++ src/sys/sys/socket.h Sun Jan 15 20:27:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: socket.h,v 1.120 2016/09/21 10:50:23 roy Exp $ */ +/* $NetBSD: socket.h,v 1.120.2.1 2017/01/15 20:27:34 bouyer Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -221,7 +221,8 @@ struct accept_filter_arg { #define AF_IEEE80211 32 /* IEEE80211 */ #define AF_MPLS 33 /* MultiProtocol Label Switching */ #define AF_ROUTE 34 /* Internal Routing Protocol */ -#define AF_MAX 35 +#define AF_CAN 35 +#define AF_MAX 36 /* * Structure used by kernel to store most @@ -330,6 +331,7 @@ struct sockaddr_storage { #define PF_BLUETOOTH AF_BLUETOOTH #define PF_MPLS AF_MPLS #define PF_ROUTE AF_ROUTE +#define PF_CAN AF_CAN #define PF_MAX AF_MAX Added files: Index: src/sys/netcan/Makefile diff -u /dev/null src/sys/netcan/Makefile:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/Makefile Sun Jan 15 20:27:33 2017 @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ + +KDIR= /sys/netcan +INCSDIR= /usr/include/netcan + +INCS= can.h + +.include <bsd.kinc.mk> Index: src/sys/netcan/can.c diff -u /dev/null src/sys/netcan/can.c:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/can.c Sun Jan 15 20:27:33 2017 @@ -0,0 +1,697 @@ +/* $NetBSD: can.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */ + +/*- + * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Robert Swindells and 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/ioctl.h> +#include <sys/protosw.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/proc.h> +#include <sys/kauth.h> + +#include <net/if.h> +#include <net/netisr.h> +#include <net/route.h> + +#include <netcan/can.h> +#include <netcan/can_pcb.h> +#include <netcan/can_var.h> + +struct canpcb canpcb; +#if 0 +struct canpcb canrawpcb; +#endif + +struct canpcbtable cbtable; + +struct ifqueue canintrq; +int canqmaxlen = IFQ_MAXLEN; + +int can_copy_output = 0; +int can_output_cnt = 0; +struct mbuf *can_lastout; + +int can_sendspace = 4096; /* really max datagram size */ +int can_recvspace = 40 * (1024 + sizeof(struct sockaddr_can)); + /* 40 1K datagrams */ +#ifndef CANHASHSIZE +#define CANHASHSIZE 128 +#endif +int canhashsize = CANHASHSIZE; + +static int can_output(struct mbuf *, struct canpcb *); + +static int can_control(struct socket *, u_long, void *, struct ifnet *); + +void +can_init(void) +{ + canintrq.ifq_maxlen = canqmaxlen; + IFQ_LOCK_INIT(&canintrq); + can_pcbinit(&cbtable, canhashsize, canhashsize); +} + +/* + * Generic control operations (ioctl's). + */ +/* ARGSUSED */ +static int +can_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp) +{ +#if 0 + struct can_ifreq *cfr = (struct can_ifreq *)data; + int error = 0; +#endif + + + switch (cmd) { + + default: + if (ifp == 0 || ifp->if_ioctl == 0) + return (EOPNOTSUPP); + return ((*ifp->if_ioctl)(ifp, cmd, data)); + } + return (0); +} + +static int +can_purgeif(struct socket *so, struct ifnet *ifp) +{ + return 0; +} + +static int +can_output(struct mbuf *m, struct canpcb *canp) +{ + struct ifnet *ifp; + int error = 0; + + if (canp == 0) { + printf("can_output: no pcb\n"); + error = EINVAL; + goto done; + } + ifp = canp->canp_ifp; + if (ifp == 0) { + error = EDESTADDRREQ; + goto done; + } + if (m->m_len <= ifp->if_mtu) { + can_output_cnt++; + error = (*ifp->if_output)(ifp, m, NULL, 0); + goto done; + } else error = EMSGSIZE; + + m_freem(m); +done: + return (error); +} + +/* + * Process a received CAN frame + * the packet is in the mbuf chain m with + * the CAN header. + */ +void +can_input(struct ifnet *ifp, struct mbuf *m) +{ + struct ifqueue *inq; + + if ((ifp->if_flags & IFF_UP) == 0) { + m_freem(m); + return; + } + + inq = &canintrq; + + IFQ_LOCK(inq); + if (IF_QFULL(inq)) { + IF_DROP(inq); + IFQ_UNLOCK(inq); + m_freem(m); + } else { + IF_ENQUEUE(inq, m); + IFQ_UNLOCK(inq); + schednetisr(NETISR_CAN); + ifp->if_ipackets++; + ifp->if_ibytes += m->m_pkthdr.len; + } +} + +void +canintr(void) +{ + int rcv_ifindex; + struct mbuf *m; + + struct sockaddr_can from; + struct canpcb *canp; + + mutex_enter(softnet_lock); + for (;;) { + IFQ_LOCK(&canintrq); + IF_DEQUEUE(&canintrq, m); + IFQ_UNLOCK(&canintrq); + + if (m == 0) /* no more queued packets */ + break; + + 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; + + TAILQ_FOREACH(canp, &cbtable.canpt_queue, canp_queue) { + struct mbuf *mc; + if (canp->canp_ifp != NULL && + canp->canp_ifp->if_index != rcv_ifindex) { + continue; + } + if (TAILQ_NEXT(canp, canp_queue) != NULL) { + /* + * we can't be sure we won't need + * the original mbuf later so copy + */ + mc = m_copym(m, 0, M_COPYALL, M_NOWAIT); + if (mc == NULL) { + /* deliver this mbuf and abort */ + mc = m; + m = NULL; + } + } else { + mc = m; + m = NULL; + } + if (sbappendaddr(&canp->canp_socket->so_rcv, + (struct sockaddr *) &from, mc, + (struct mbuf *) 0) == 0) { + m_freem(mc); + } else + sorwakeup(canp->canp_socket); + if (m == NULL) + break; + } + /* If it didn't go anywhere just delete it */ + if (m) { + m_freem(m); + } + } + mutex_exit(softnet_lock); +} + +static int +can_attach(struct socket *so, int proto) +{ + /*struct canpcb *canp;*/ + int error; + + KASSERT(sotocanpcb(so) == NULL); + + /* Assign the lock (must happen even if we will error out). */ + sosetlock(so); + +#ifdef MBUFTRACE + so->so_mowner = &can_mowner; + so->so_rcv.sb_mowner = &can_rx_mowner; + so->so_snd.sb_mowner = &can_tx_mowner; +#endif + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = soreserve(so, can_sendspace, can_recvspace); + if (error) { + return error; + } + } + + error = can_pcballoc(so, &cbtable); + if (error) { + return error; + } + /*canp = sotocanpcb(so);*/ + KASSERT(solocked(so)); + + return error; +} + +static void +can_detach(struct socket *so) +{ + struct canpcb *canp; + + KASSERT(solocked(so)); + canp = sotocanpcb(so); + can_pcbdetach(canp); +} + +static int +can_accept(struct socket *so, struct sockaddr *nam) +{ + KASSERT(solocked(so)); + + panic("can_accept"); + + return EOPNOTSUPP; +} + +static int +can_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) +{ + struct canpcb *canp = sotocanpcb(so); + struct sockaddr_can *scan = (struct sockaddr_can *)nam; + + KASSERT(solocked(so)); + KASSERT(nam != NULL); + + return can_pcbbind(canp, scan, l); +} + +static int +can_listen(struct socket *so, struct lwp *l) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +can_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) +{ + struct canpcb *canp = sotocanpcb(so); + int error = 0; + + KASSERT(solocked(so)); + KASSERT(canp != NULL); + KASSERT(nam != NULL); + + error = can_pcbconnect(canp, (struct sockaddr_can *)nam); + if (! error) + soisconnected(so); + return error; +} + +static int +can_connect2(struct socket *so, struct socket *so2) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +can_disconnect(struct socket *so) +{ + struct canpcb *canp = sotocanpcb(so); + + KASSERT(solocked(so)); + KASSERT(canp != NULL); + + /*soisdisconnected(so);*/ + so->so_state &= ~SS_ISCONNECTED; /* XXX */ + can_pcbdisconnect(canp); + can_pcbstate(canp, CANP_BOUND); /* XXX */ + return 0; +} + +static int +can_shutdown(struct socket *so) +{ + KASSERT(solocked(so)); + + socantsendmore(so); + return 0; +} + +static int +can_abort(struct socket *so) +{ + KASSERT(solocked(so)); + + panic("can_abort"); + + return EOPNOTSUPP; +} + +static int +can_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) +{ + return can_control(so, cmd, nam, ifp); +} + +static int +can_stat(struct socket *so, struct stat *ub) +{ + KASSERT(solocked(so)); + + /* stat: don't bother with a blocksize. */ + return 0; +} + +static int +can_peeraddr(struct socket *so, struct sockaddr *nam) +{ + KASSERT(solocked(so)); + KASSERT(sotocanpcb(so) != NULL); + KASSERT(nam != NULL); + + return EOPNOTSUPP; +} + +static int +can_sockaddr(struct socket *so, struct sockaddr *nam) +{ + KASSERT(solocked(so)); + KASSERT(sotocanpcb(so) != NULL); + KASSERT(nam != NULL); + + can_setsockaddr(sotocanpcb(so), (struct sockaddr_can *)nam); + + return 0; +} + +static int +can_rcvd(struct socket *so, int flags, struct lwp *l) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +can_recvoob(struct socket *so, struct mbuf *m, int flags) +{ + KASSERT(solocked(so)); + + return EOPNOTSUPP; +} + +static int +can_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, + struct mbuf *control, struct lwp *l) +{ + struct canpcb *canp = sotocanpcb(so); + int error = 0; + int s; + + if (control && control->m_len) { + return EINVAL; + } + + if (nam) { + if ((so->so_state & SS_ISCONNECTED) != 0) { + return EISCONN; + } + s = splnet(); + error = can_pcbbind(canp, (struct sockaddr_can *)nam, l); + if (error) { + splx(s); + return error; + } + } else { + if ((so->so_state & SS_ISCONNECTED) == 0) { + return EDESTADDRREQ; + } + } + error = can_output(m, canp); + if (nam) { + struct sockaddr_can lscan; + memset(&lscan, 0, sizeof(lscan)); + lscan.can_family = AF_CAN; + lscan.can_len = sizeof(lscan); + can_pcbbind(canp, &lscan, l); + } + return error; +} + +static int +can_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) +{ + KASSERT(solocked(so)); + + m_freem(m); + m_freem(control); + + return EOPNOTSUPP; +} + +#if 0 +int +can_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct lwp *l) +{ + struct canpcb *canp; + int s; + int error = 0; + + if (req == PRU_CONTROL) + return (can_control(so, (long)m, nam, + (struct ifnet *)control)); + + if (req == PRU_PURGEIF) { +#if 0 + can_pcbpurgeif0(&udbtable, (struct ifnet *)control); + can_purgeif((struct ifnet *)control); + can_pcbpurgeif(&udbtable, (struct ifnet *)control); +#endif + return (0); + } + + s = splsoftnet(); + canp = sotocanpcb(so); +#ifdef DIAGNOSTIC + if (req != PRU_SEND && req != PRU_SENDOOB && control) + panic("can_usrreq: unexpected control mbuf"); +#endif + if (canp == 0 && req != PRU_ATTACH) { + printf("can_usrreq: no pcb %p %d\n", canp, req); + error = EINVAL; + goto release; + } + + /* + * Note: need to block can_input while changing + * the can pcb queue and/or pcb addresses. + */ + switch (req) { + + case PRU_ATTACH: + if (canp != 0) { + error = EISCONN; + break; + } +#ifdef MBUFTRACE + so->so_mowner = &can_mowner; + so->so_rcv.sb_mowner = &can_rx_mowner; + so->so_snd.sb_mowner = &can_tx_mowner; +#endif + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = soreserve(so, can_sendspace, can_recvspace); + if (error) + break; + } + error = can_pcballoc(so, &cbtable); + if (error) + break; + canp = sotocanpcb(so); +#if 0 + inp->inp_ip.ip_ttl = ip_defttl; +#endif + break; + + case PRU_DETACH: + can_pcbdetach(canp); + break; + + case PRU_BIND: + error = can_pcbbind(canp, nam, l); + break; + + case PRU_LISTEN: + error = EOPNOTSUPP; + break; + + case PRU_CONNECT: + error = can_pcbconnect(canp, nam); + if (error) + break; + soisconnected(so); + break; + + case PRU_CONNECT2: + error = EOPNOTSUPP; + break; + + case PRU_DISCONNECT: + /*soisdisconnected(so);*/ + so->so_state &= ~SS_ISCONNECTED; /* XXX */ + can_pcbdisconnect(canp); + can_pcbstate(canp, CANP_BOUND); /* XXX */ + break; + + case PRU_SHUTDOWN: + socantsendmore(so); + break; + + case PRU_RCVD: + error = EOPNOTSUPP; + break; + + case PRU_SEND: + break; + + case PRU_SENSE: + /* + * stat: don't bother with a blocksize. + */ + splx(s); + return (0); + + case PRU_RCVOOB: + error = EOPNOTSUPP; + break; + + case PRU_SENDOOB: + m_freem(control); + m_freem(m); + error = EOPNOTSUPP; + break; + + case PRU_SOCKADDR: + + break; + + case PRU_PEERADDR: + error = EOPNOTSUPP; + break; + + default: + panic("can_usrreq"); + } + +release: + splx(s); + return (error); +} +#endif + +#if 0 +static void +can_notify(struct canpcb *canp, int errno) +{ + + canp->canp_socket->so_error = errno; + sorwakeup(canp->canp_socket); + sowwakeup(canp->canp_socket); +} + +void * +can_ctlinput(int cmd, struct sockaddr *sa, void *v) +{ + struct ip *ip = v; + struct canhdr *uh; + void (*notify) __P((struct inpcb *, int)) = can_notify; + int errno; + + if (sa->sa_family != AF_CAN + || sa->sa_len != sizeof(struct sockaddr_can)) + return NULL; + if ((unsigned)cmd >= PRC_NCMDS) + return NULL; + errno = inetctlerrmap[cmd]; + if (PRC_IS_REDIRECT(cmd)) + notify = in_rtchange, ip = 0; + else if (cmd == PRC_HOSTDEAD) + ip = 0; + else if (errno == 0) + return NULL; + if (ip) { + uh = (struct canhdr *)((caddr_t)ip + (ip->ip_hl << 2)); + in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport, + ip->ip_src, uh->uh_sport, errno, notify); + + /* XXX mapped address case */ + } else + can_pcbnotifyall(&cbtable, satoscan(sa)->scan_addr, errno, + notify); + return NULL; +} +#endif + +PR_WRAP_USRREQS(can) +#define can_attach can_attach_wrapper +#define can_detach can_detach_wrapper +#define can_accept can_accept_wrapper +#define can_bind can_bind_wrapper +#define can_listen can_listen_wrapper +#define can_connect can_connect_wrapper +#define can_connect2 can_connect2_wrapper +#define can_disconnect can_disconnect_wrapper +#define can_shutdown can_shutdown_wrapper +#define can_abort can_abort_wrapper +#define can_ioctl can_ioctl_wrapper +#define can_stat can_stat_wrapper +#define can_peeraddr can_peeraddr_wrapper +#define can_sockaddr can_sockaddr_wrapper +#define can_rcvd can_rcvd_wrapper +#define can_recvoob can_recvoob_wrapper +#define can_send can_send_wrapper +#define can_sendoob can_sendoob_wrapper +#define can_purgeif can_purgeif_wrapper + +const struct pr_usrreqs can_usrreqs = { + .pr_attach = can_attach, + .pr_detach = can_detach, + .pr_accept = can_accept, + .pr_bind = can_bind, + .pr_listen = can_listen, + .pr_connect = can_connect, + .pr_connect2 = can_connect2, + .pr_disconnect = can_disconnect, + .pr_shutdown = can_shutdown, + .pr_abort = can_abort, + .pr_ioctl = can_ioctl, + .pr_stat = can_stat, + .pr_peeraddr = can_peeraddr, + .pr_sockaddr = can_sockaddr, + .pr_rcvd = can_rcvd, + .pr_recvoob = can_recvoob, + .pr_send = can_send, + .pr_sendoob = can_sendoob, + .pr_purgeif = can_purgeif, +}; Index: src/sys/netcan/can.h diff -u /dev/null src/sys/netcan/can.h:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/can.h Sun Jan 15 20:27:33 2017 @@ -0,0 +1,133 @@ +/* $NetBSD: can.h,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */ + +/*- + * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Robert Swindells and 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. + */ + +#ifndef _NETCAN_CAN_H +#define _NETCAN_CAN_H + +#include <sys/featuretest.h> +#include <machine/int_types.h> + + +/* Definitions compatible (as much as possible) with socketCAN */ + +/* + * CAN id structure + * bits 0-28 : CAN identifier (11/29 bits, see bit 31) + * bit2 29-31 : see below + */ + +typedef uint32_t canid_t; +typedef uint32_t can_err_mask_t; + +/* canid_t bits 29-31 descriptions */ +#define CAN_EFF_FLAG 0x80000000U /* extended frame format */ +#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */ +#define CAN_ERR_FLAG 0x20000000U /* error message frame */ + +/* valid bits in CAN ID for frame formats */ +#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */ +#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */ +#define CAN_ERR_MASK 0x1FFFFFFFU /* error frame format */ + +/* CAN payload length and DLC definitions according to ISO 11898-1 */ +#define CAN_MAX_DLC 8 +#define CAN_MAX_DLEN 8 + +/* CAN frame */ +struct can_frame { + canid_t can_id; /* ID + EFF/RTR/ERR flags */ + uint8_t can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */ + uint8_t __pad; + uint8_t __res0; + uint8_t __res1; + uint8_t data[CAN_MAX_DLEN]; +}; + +#define CAN_MTU (sizeof(struct can_frame)) + +/* protocols */ +#define CAN_RAW 1 /* RAW sockets */ +#define CAN_NPROTO 2 + +#define SOL_CAN_BASE 100 + +/* + * Socket address, CAN style + */ +struct sockaddr_can { + u_int8_t can_len; + sa_family_t can_family; + int can_ifindex; + union { + /* transport protocol class address information (e.g. ISOTP) */ + struct { canid_t rx_id, tx_id; } tp; + /* reserved for future CAN protocols address information */ + } can_addr; +}; + +/* + * Options for use with [gs]etsockopt + * First word of comment is data type; bool is stored in int. + */ + +#define CAN_RAW_FILTER 1 /* struct can_filter: set filter */ + +/* + * CAN ID based filter + * checks received can_id & can_filter.can_mask against + * can_filter.can_id & can_filter.can_mask + * valid flags for can_id: + * CAN_INV_FILTER: invert filter + * valid flags for can_mask: + * CAN_ERR_FLAG: filter for error message frames + */ +struct can_filter { + canid_t can_id; + canid_t can_mask; +}; + +#define CAN_INV_FILTER 0x20000000U + +#ifdef _NETBSD_SOURCE + +/* CAN sockets ioctl */ + +#define SIOCSCANBAUD _IOW('i', 134, int) /* set interface speed */ +#define SIOCGCANBAUD _IOR('i', 135, int) /* get interface speed */ + +#ifdef _KERNEL + +#define satoscan(sa) ((struct sockaddr_can *)(sa)) +#define scantosa(scan) ((struct sockaddr *)(scan)) + +#endif /* _KERNEL */ +#endif /* _NETBSD_SOURCE */ +#endif /* _NETCAN_CAN_H */ Index: src/sys/netcan/can_pcb.c diff -u /dev/null src/sys/netcan/can_pcb.c:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/can_pcb.c Sun Jan 15 20:27:33 2017 @@ -0,0 +1,283 @@ +/* $NetBSD: can_pcb.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */ + +/*- + * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Robert Swindells and 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: can_pcb.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#include <sys/time.h> +#include <sys/pool.h> +#include <sys/proc.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netcan/can.h> +#include <netcan/can_var.h> +#include <netcan/can_pcb.h> + +#define CANPCBHASH_BIND(table, ifindex) \ + &(table)->canpt_bindhashtbl[ \ + (ifindex) & (table)->canpt_bindhash] +#define CANPCBHASH_CONNECT(table, ifindex) \ + &(table)->canpt_connecthashtbl[ \ + (ifindex) & (table)->canpt_bindhash] + +struct pool canpcb_pool; + +void +can_pcbinit(struct canpcbtable *table, int bindhashsize, int connecthashsize) +{ + static int canpcb_pool_initialized; + + if (canpcb_pool_initialized == 0) { + pool_init(&canpcb_pool, sizeof(struct canpcb), 0, 0, 0, + "canpcbpl", NULL, IPL_SOFTNET); + canpcb_pool_initialized = 1; + } + + TAILQ_INIT(&table->canpt_queue); + table->canpt_bindhashtbl = hashinit(bindhashsize, HASH_LIST, true, + &table->canpt_bindhash); + table->canpt_connecthashtbl = hashinit(connecthashsize, HASH_LIST, + true, &table->canpt_connecthash); +} + +int +can_pcballoc(struct socket *so, void *v) +{ + struct canpcbtable *table = v; + struct canpcb *canp; + int s; + + s = splnet(); + canp = pool_get(&canpcb_pool, PR_NOWAIT); + splx(s); + if (canp == NULL) + return (ENOBUFS); + memset(canp, 0, sizeof(*canp)); + canp->canp_table = table; + canp->canp_socket = so; + + so->so_pcb = canp; + s = splnet(); + TAILQ_INSERT_HEAD(&table->canpt_queue, canp, canp_queue); + can_pcbstate(canp, CANP_ATTACHED); + splx(s); + return (0); +} + +int +can_pcbbind(void *v, struct sockaddr_can *scan, struct lwp *l) +{ + struct canpcb *canp = v; + + if (scan->can_family != AF_CAN) + return (EAFNOSUPPORT); + if (scan->can_ifindex != 0) { + canp->canp_ifp = if_byindex(scan->can_ifindex); + if (canp->canp_ifp == NULL) + return (EADDRNOTAVAIL); + soisconnected(canp->canp_socket); + } else { + canp->canp_ifp = NULL; + canp->canp_socket->so_state &= ~SS_ISCONNECTED; /* XXX */ + } + can_pcbstate(canp, CANP_BOUND); + return 0; +} + +/* + * Connect from a socket to a specified address. + */ +int +can_pcbconnect(void *v, struct sockaddr_can *scan) +{ +#if 0 + struct canpcb *canp = v; + struct sockaddr_can *ifaddr = NULL; + int error; +#endif + + if (scan->can_family != AF_CAN) + return (EAFNOSUPPORT); +#if 0 + memcpy(&canp->canp_dst, scan, sizeof(struct sockaddr_can)); + can_pcbstate(canp, CANP_CONNECTED); + return 0; +#endif + return EOPNOTSUPP; +} + +void +can_pcbdisconnect(void *v) +{ + struct canpcb *canp = v; + + can_pcbstate(canp, CANP_BOUND); + if (canp->canp_socket->so_state & SS_NOFDREF) + can_pcbdetach(canp); +} + +void +can_pcbdetach(void *v) +{ + struct canpcb *canp = v; + struct socket *so = canp->canp_socket; + int s; + + KASSERT(mutex_owned(softnet_lock)); + so->so_pcb = NULL; + s = splnet(); + can_pcbstate(canp, CANP_ATTACHED); + TAILQ_REMOVE(&canp->canp_table->canpt_queue, canp, canp_queue); + splx(s); + sofree(so); /* sofree drops the lock */ + pool_put(&canpcb_pool, canp); + mutex_enter(softnet_lock); +} + +void +can_setsockaddr(struct canpcb *canp, struct sockaddr_can *scan) +{ + + memset(scan, 0, sizeof (*scan)); + scan->can_family = AF_CAN; + scan->can_len = sizeof(*scan); + scan->can_ifindex = canp->canp_ifp->if_index; +} + +#if 0 +/* + * Pass some notification to all connections of a protocol + * associated with address dst. The local address and/or port numbers + * may be specified to limit the search. The "usual action" will be + * taken, depending on the ctlinput cmd. The caller must filter any + * cmds that are uninteresting (e.g., no error in the map). + * Call the protocol specific routine (if any) to report + * any errors for each matching socket. + * + * Must be called at splsoftnet. + */ +int +can_pcbnotify(struct canpcbtable *table, u_int32_t faddr, u_int32_t laddr, + int errno, void (*notify)(struct canpcb *, int)) +{ + struct canpcbhead *head; + struct canpcb *canp, *ncanp; + int nmatch; + + if (faddr == 0 || notify == 0) + return (0); + + nmatch = 0; + head = CANPCBHASH_CONNECT(table, faddr, laddr); + for (canp = LIST_FIRST(head); canp != NULL; canp = ncanp) { + ncanp = LIST_NEXT(canp, canp_hash); + if (canp->canp_faddr == faddr && + canp->canp_laddr == laddr) { + (*notify)(canp, errno); + nmatch++; + } + } + return (nmatch); +} + +void +can_pcbnotifyall(struct canpcbtable *table, u_int32_t faddr, int errno, + void (*notify)(struct canpcb *, int)) +{ + struct canpcb *canp, *ncanp; + + if (faddr == 0 || notify == 0) + return; + + TAILQ_FOREACH_SAFE(canp, &table->canpt_queue, canp_queue, ncanp) { + if (canp->canp_faddr == faddr) + (*notify)(canp, errno); + } +} +#endif + +#if 0 +void +can_pcbpurgeif0(struct canpcbtable *table, struct ifnet *ifp) +{ + struct canpcb *canp, *ncanp; + struct ip_moptions *imo; + int i, gap; + +} + +void +can_pcbpurgeif(struct canpcbtable *table, struct ifnet *ifp) +{ + struct canpcb *canp, *ncanp; + + for (canp = CIRCLEQ_FIRST(&table->canpt_queue); + canp != (void *)&table->canpt_queue; + canp = ncanp) { + ncanp = CIRCLEQ_NEXT(canp, canp_queue); + } +} +#endif + + + +void +can_pcbstate(struct canpcb *canp, int state) +{ + int ifindex = canp->canp_ifp ? canp->canp_ifp->if_index : 0; + + if (canp->canp_state > CANP_ATTACHED) + LIST_REMOVE(canp, canp_hash); + + switch (state) { + case CANP_BOUND: + LIST_INSERT_HEAD(CANPCBHASH_BIND(canp->canp_table, + ifindex), canp, canp_hash); + break; + case CANP_CONNECTED: + LIST_INSERT_HEAD(CANPCBHASH_CONNECT(canp->canp_table, + ifindex), canp, canp_hash); + break; + } + + canp->canp_state = state; +} Index: src/sys/netcan/can_pcb.h diff -u /dev/null src/sys/netcan/can_pcb.h:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/can_pcb.h Sun Jan 15 20:27:33 2017 @@ -0,0 +1,98 @@ +/* $NetBSD: can_pcb.h,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */ + +/*- + * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Robert Swindells and 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. + */ + +#ifndef _NETCAN_CAN_PCB_H_ +#define _NETCAN_CAN_PCB_H_ + +#include <sys/queue.h> + +/* + * Common structure pcb for can protocol implementation. + * Here are stored pointers to local and foreign host table + * entries, local and foreign socket numbers, and pointers + * up (to a socket structure) and down (to a protocol-specific) + * control block. + */ +struct canpcbpolicy; + + +struct canpcb { + LIST_ENTRY(canpcb) canp_hash; + LIST_ENTRY(canpcb) canp_lhash; + TAILQ_ENTRY(canpcb) canp_queue; + int canp_state; + struct socket *canp_socket; /* back pointer to socket */ + struct ifnet *canp_ifp; + struct canpcbtable *canp_table; +}; + +LIST_HEAD(canpcbhead, canpcb); + +#define canp_faddr canp_dst.scan_addr + +TAILQ_HEAD(canpcbqueue, canpcb); + +struct canpcbtable { + struct canpcbqueue canpt_queue; + struct canpcbhead *canpt_bindhashtbl; + struct canpcbhead *canpt_connecthashtbl; + u_long canpt_bindhash; + u_long canpt_connecthash; +}; + +/* states in inp_state: */ +#define CANP_ATTACHED 0 +#define CANP_BOUND 1 +#define CANP_CONNECTED 2 + +/* flags in inp_flags: */ + +#define sotocanpcb(so) ((struct canpcb *)(so)->so_pcb) + +#ifdef _KERNEL +void can_losing(struct canpcb *); +int can_pcballoc (struct socket *, void *); +int can_pcbbind(void *, struct sockaddr_can *, struct lwp *); +int can_pcbconnect(void *, struct sockaddr_can *); +void can_pcbdetach(void *); +void can_pcbdisconnect(void *); +void can_pcbinit(struct canpcbtable *, int, int); +int can_pcbnotify(struct canpcbtable *, u_int32_t, + u_int32_t, int, void (*)(struct canpcb *, int)); +void can_pcbnotifyall(struct canpcbtable *, u_int32_t, int, + void (*)(struct canpcb *, int)); +void can_pcbpurgeif0(struct canpcbtable *, struct ifnet *); +void can_pcbpurgeif(struct canpcbtable *, struct ifnet *); +void can_pcbstate(struct canpcb *, int); +void can_setsockaddr(struct canpcb *, struct sockaddr_can *); +#endif + +#endif /* _NETCAN_CAN_PCB_H_ */ Index: src/sys/netcan/can_proto.c diff -u /dev/null src/sys/netcan/can_proto.c:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/can_proto.c Sun Jan 15 20:27:33 2017 @@ -0,0 +1,75 @@ +/* $NetBSD: can_proto.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */ + +/*- + * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Robert Swindells and 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: can_proto.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $"); + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/mbuf.h> + +#include <net/if.h> +#include <net/radix.h> +#include <net/route.h> + +/* + * CAN protocol family + */ +#include <netcan/can.h> +#include <netcan/can_var.h> + +DOMAIN_DEFINE(candomain); /* forward declare and add to link set */ + +const struct protosw cansw[] = { +{ + .pr_type = SOCK_RAW, + .pr_domain = &candomain, + .pr_init = can_init, + .pr_flags = PR_ATOMIC|PR_ADDR, + .pr_usrreqs = &can_usrreqs, +} +}; + +struct domain candomain = { + .dom_family = PF_CAN, + .dom_name = "can", + .dom_init = can_init, + .dom_externalize = NULL, .dom_dispose = NULL, + .dom_protosw = cansw, + .dom_protoswNPROTOSW = &cansw[__arraycount(cansw)], + .dom_ifqueues = { &canintrq, NULL }, + .dom_link = { NULL }, + .dom_mowner = MOWNER_INIT("",""), + .dom_sa_cmpofs = offsetof(struct sockaddr_can, can_ifindex), + .dom_sa_cmplen = sizeof(int) +}; Index: src/sys/netcan/can_var.h diff -u /dev/null src/sys/netcan/can_var.h:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/can_var.h Sun Jan 15 20:27:33 2017 @@ -0,0 +1,56 @@ +/* $NetBSD: can_var.h,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ */ + +/*- + * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Robert Swindells and 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. + */ + +#ifndef _NETCAN_CAN_VAR_H_ +#define _NETCAN_CAN_VAR_H_ + +#include <sys/queue.h> + +struct can_ifreq { + char cfr_name[IFNAMSIZ]; /* if name, e.g. "sja0" */ +}; + +#ifdef _KERNEL + +extern struct ifqueue canintrq; +extern struct domain candomain; + +extern const struct pr_usrreqs can_usrreqs; + +void can_input(struct ifnet *, struct mbuf *); +void *can_ctlinput(int, struct sockaddr *, void *); +int can_ctloutput(int, struct socket *, int, int, struct mbuf **); +void can_init(void); +void canintr(void); + +#endif + +#endif Index: src/sys/netcan/files.netcan diff -u /dev/null src/sys/netcan/files.netcan:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/files.netcan Sun Jan 15 20:27:33 2017 @@ -0,0 +1,8 @@ +# $NetBSD: files.netcan,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $ + +defflag opt_can.h CAN # ISO-15765 CAN network stack + +file netcan/can.c can +file netcan/can_proto.c can +file netcan/can_pcb.c can +file net/if_canloop.c canloop Index: src/sys/netcan/if_canloop.c diff -u /dev/null src/sys/netcan/if_canloop.c:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/netcan/if_canloop.c Sun Jan 15 20:27:33 2017 @@ -0,0 +1,232 @@ +/* $NetBSD: if_canloop.c,v 1.1.2.1 2017/01/15 20:27:33 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. + */ + + +/* + * Loopback interface driver for the CAN protocol + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: if_canloop.c,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $"); + +#ifdef _KERNEL_OPT +#include "opt_can.h" +#include "opt_net_mpsafe.h" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/device.h> +#include <sys/module.h> + +#include <sys/cpu.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/netisr.h> + +#ifdef CAN +#include <netcan/can.h> +#endif +#include <net/bpf.h> + +void canloopattach(int); +void canloopinit(void); +static int canloop_clone_create(struct if_clone *, int); +static int canloop_clone_destroy(struct ifnet *); +static int canloop_ioctl(struct ifnet *, u_long, void *); +static int canloop_output(struct ifnet *, + struct mbuf *, const struct sockaddr *, const struct rtentry *); + +static int canloop_count; + +static struct if_clone canloop_cloner = + IF_CLONE_INITIALIZER("canlo", canloop_clone_create, canloop_clone_destroy); + +void +canloopattach(int n) +{ + + /* + * Nothing to do here, initialization is handled by the + * module initialization code in canloopnit() below). + */ +} + +void +canloopinit(void) +{ + + canloop_count = 0; + if_clone_attach(&canloop_cloner); +} + +static int +canloopdetach(void) +{ + if (canloop_count > 0) + return EBUSY; + if_clone_detach(&canloop_cloner); + return 0; +} + +static int +canloop_clone_create(struct if_clone *ifc, int unit) +{ + struct ifnet *ifp; + + ifp = if_alloc(IFT_OTHER); + + if_initname(ifp, ifc->ifc_name, unit); + + ifp->if_mtu = sizeof(struct can_frame); + ifp->if_flags = IFF_LOOPBACK | IFF_RUNNING; + ifp->if_extflags = IFEF_OUTPUT_MPSAFE; + ifp->if_ioctl = canloop_ioctl; + ifp->if_output = canloop_output; + ifp->if_type = IFT_OTHER; + ifp->if_hdrlen = 0; + ifp->if_addrlen = 0; + ifp->if_dlt = DLT_CAN_SOCKETCAN; + IFQ_SET_READY(&ifp->if_snd); + if_attach(ifp); + if_alloc_sadl(ifp); + bpf_attach(ifp, DLT_CAN_SOCKETCAN, sizeof(u_int)); +#ifdef MBUFTRACE + ifp->if_mowner = malloc(sizeof(struct mowner), M_DEVBUF, + M_WAITOK | M_ZERO); + strlcpy(ifp->if_mowner->mo_name, ifp->if_xname, + sizeof(ifp->if_mowner->mo_name)); + MOWNER_ATTACH(ifp->if_mowner); +#endif + canloop_count++; + + return (0); +} + +static int +canloop_clone_destroy(struct ifnet *ifp) +{ + +#ifdef MBUFTRACE + MOWNER_DETACH(ifp->if_mowner); + free(ifp->if_mowner, M_DEVBUF); +#endif + + bpf_detach(ifp); + if_detach(ifp); + + if_free(ifp); + canloop_count--; + KASSERT(canloop_count >= 0); + return (0); +} + +static int +canloop_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, + const struct rtentry *rt) +{ + int error = 0; + size_t pktlen; + + MCLAIM(m, ifp->if_mowner); + + KERNEL_LOCK(1, NULL); + + if ((m->m_flags & M_PKTHDR) == 0) + panic("canloop_output: no header mbuf"); + if (ifp->if_flags & IFF_LOOPBACK) + bpf_mtap_af(ifp, AF_CAN, m); + m_set_rcvif(m, ifp); + + pktlen = m->m_pkthdr.len; + ifp->if_opackets++; + ifp->if_obytes += pktlen; + + m_tag_delete_nonpersistent(m); + +#ifdef CAN + can_input(ifp, m); +#else + printf("%s: can't handle CAN packet\n", ifp->if_xname); + m_freem(m); + error = EAFNOSUPPORT; +#endif + + KERNEL_UNLOCK_ONE(NULL); + return error; +} + + +/* + * Process an ioctl request. + */ +/* ARGSUSED */ +static int +canloop_ioctl(struct ifnet *ifp, u_long cmd, void *data) +{ + struct ifreq *ifr = data; + int error = 0; + + switch (cmd) { + + case SIOCINITIFADDR: + error = EAFNOSUPPORT; + break; + + case SIOCSIFMTU: + if ((unsigned)ifr->ifr_mtu != sizeof(struct can_frame)) + error = EINVAL; + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + error = EAFNOSUPPORT; + break; + + default: + error = ifioctl_common(ifp, cmd, data); + } + return (error); +} + +/* + * Module infrastructure + */ +#include "../net/if_module.h" + +IF_MODULE(MODULE_CLASS_DRIVER, canloop, "") Index: src/sys/rump/net/lib/libnetcan/Makefile diff -u /dev/null src/sys/rump/net/lib/libnetcan/Makefile:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/rump/net/lib/libnetcan/Makefile Sun Jan 15 20:27:34 2017 @@ -0,0 +1,20 @@ +# $NetBSD: Makefile,v 1.1.2.1 2017/01/15 20:27:34 bouyer Exp $ +# + +NOLINT= #defined + +.include <bsd.own.mk> + +.PATH: ${.CURDIR}/../../../../netcan + +LIB= rumpnet_netcan +COMMENT=CAN (PF_CAN) + +IOCONF= NETCAN.ioconf + +SRCS= can.c can_pcb.c can_proto.c if_canloop.c + +SRCS+= netcan_component.c + +.include <bsd.lib.mk> +.include <bsd.klinks.mk> Index: src/sys/rump/net/lib/libnetcan/NETCAN.ioconf diff -u /dev/null src/sys/rump/net/lib/libnetcan/NETCAN.ioconf:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/rump/net/lib/libnetcan/NETCAN.ioconf Sun Jan 15 20:27:34 2017 @@ -0,0 +1,7 @@ +# $NetBSD: NETCAN.ioconf,v 1.1.2.1 2017/01/15 20:27:34 bouyer Exp $ + +ioconf netcan + +include "conf/files" + +pseudo-device canloop Index: src/sys/rump/net/lib/libnetcan/netcan_component.c diff -u /dev/null src/sys/rump/net/lib/libnetcan/netcan_component.c:1.1.2.1 --- /dev/null Sun Jan 15 20:27:34 2017 +++ src/sys/rump/net/lib/libnetcan/netcan_component.c Sun Jan 15 20:27:34 2017 @@ -0,0 +1,52 @@ +/* $NetBSD: netcan_component.c,v 1.1.2.1 2017/01/15 20:27:34 bouyer Exp $ */ + +/* + * Copyright (c) 2010 Antti Kantee. All Rights Reserved. + * + * 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 AUTHOR ``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 AUTHOR 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: netcan_component.c,v 1.1.2.1 2017/01/15 20:27:34 bouyer Exp $"); + +#include <sys/param.h> +#include <sys/domain.h> +#include <sys/protosw.h> + +#include <rump-sys/kern.h> +#include <rump-sys/net.h> +#include <net/netisr.h> +#include <netcan/can_var.h> + +RUMP_COMPONENT(RUMP_COMPONENT_NET) +{ + extern struct domain candomain; + + domain_attach(&candomain); + rump_netisr_register(NETISR_CAN, canintr); +} + +void canloopinit(void); +RUMP_COMPONENT(RUMP_COMPONENT_NET_IF) +{ + canloopinit(); +}