Home | History | Annotate | Line # | Download | only in netcan
can.c revision 1.1.2.9
      1  1.1.2.9  bouyer /*	$NetBSD: can.c,v 1.1.2.9 2017/04/19 17:52:37 bouyer Exp $	*/
      2  1.1.2.1  bouyer 
      3  1.1.2.1  bouyer /*-
      4  1.1.2.1  bouyer  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
      5  1.1.2.1  bouyer  * All rights reserved.
      6  1.1.2.1  bouyer  *
      7  1.1.2.1  bouyer  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1.2.1  bouyer  * by Robert Swindells and Manuel Bouyer
      9  1.1.2.1  bouyer  *
     10  1.1.2.1  bouyer  * Redistribution and use in source and binary forms, with or without
     11  1.1.2.1  bouyer  * modification, are permitted provided that the following conditions
     12  1.1.2.1  bouyer  * are met:
     13  1.1.2.1  bouyer  * 1. Redistributions of source code must retain the above copyright
     14  1.1.2.1  bouyer  *    notice, this list of conditions and the following disclaimer.
     15  1.1.2.1  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1.2.1  bouyer  *    notice, this list of conditions and the following disclaimer in the
     17  1.1.2.1  bouyer  *    documentation and/or other materials provided with the distribution.
     18  1.1.2.1  bouyer  *
     19  1.1.2.1  bouyer  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1.2.1  bouyer  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1.2.1  bouyer  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1.2.1  bouyer  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1.2.1  bouyer  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1.2.1  bouyer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1.2.1  bouyer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1.2.1  bouyer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1.2.1  bouyer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1.2.1  bouyer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1.2.1  bouyer  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1.2.1  bouyer  */
     31  1.1.2.1  bouyer 
     32  1.1.2.1  bouyer #include <sys/cdefs.h>
     33  1.1.2.9  bouyer __KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.9 2017/04/19 17:52:37 bouyer Exp $");
     34  1.1.2.1  bouyer 
     35  1.1.2.1  bouyer #include <sys/param.h>
     36  1.1.2.1  bouyer #include <sys/systm.h>
     37  1.1.2.1  bouyer #include <sys/mbuf.h>
     38  1.1.2.1  bouyer #include <sys/ioctl.h>
     39  1.1.2.2  bouyer #include <sys/domain.h>
     40  1.1.2.1  bouyer #include <sys/protosw.h>
     41  1.1.2.1  bouyer #include <sys/errno.h>
     42  1.1.2.1  bouyer #include <sys/socket.h>
     43  1.1.2.1  bouyer #include <sys/socketvar.h>
     44  1.1.2.1  bouyer #include <sys/proc.h>
     45  1.1.2.1  bouyer #include <sys/kauth.h>
     46  1.1.2.1  bouyer 
     47  1.1.2.1  bouyer #include <net/if.h>
     48  1.1.2.5  bouyer #include <net/if_types.h>
     49  1.1.2.1  bouyer #include <net/netisr.h>
     50  1.1.2.1  bouyer #include <net/route.h>
     51  1.1.2.1  bouyer 
     52  1.1.2.1  bouyer #include <netcan/can.h>
     53  1.1.2.1  bouyer #include <netcan/can_pcb.h>
     54  1.1.2.1  bouyer #include <netcan/can_var.h>
     55  1.1.2.1  bouyer 
     56  1.1.2.1  bouyer struct canpcb canpcb;
     57  1.1.2.1  bouyer #if 0
     58  1.1.2.1  bouyer struct canpcb canrawpcb;
     59  1.1.2.1  bouyer #endif
     60  1.1.2.1  bouyer 
     61  1.1.2.1  bouyer struct	canpcbtable cbtable;
     62  1.1.2.1  bouyer 
     63  1.1.2.1  bouyer struct ifqueue	canintrq;
     64  1.1.2.1  bouyer int	canqmaxlen = IFQ_MAXLEN;
     65  1.1.2.1  bouyer 
     66  1.1.2.1  bouyer int can_copy_output = 0;
     67  1.1.2.1  bouyer int can_output_cnt = 0;
     68  1.1.2.1  bouyer struct mbuf *can_lastout;
     69  1.1.2.1  bouyer 
     70  1.1.2.1  bouyer int	can_sendspace = 4096;		/* really max datagram size */
     71  1.1.2.1  bouyer int	can_recvspace = 40 * (1024 + sizeof(struct sockaddr_can));
     72  1.1.2.1  bouyer 					/* 40 1K datagrams */
     73  1.1.2.1  bouyer #ifndef CANHASHSIZE
     74  1.1.2.1  bouyer #define	CANHASHSIZE	128
     75  1.1.2.1  bouyer #endif
     76  1.1.2.1  bouyer int	canhashsize = CANHASHSIZE;
     77  1.1.2.1  bouyer 
     78  1.1.2.1  bouyer static int can_output(struct mbuf *, struct canpcb *);
     79  1.1.2.1  bouyer 
     80  1.1.2.1  bouyer static int can_control(struct socket *, u_long, void *, struct ifnet *);
     81  1.1.2.1  bouyer 
     82  1.1.2.1  bouyer void
     83  1.1.2.1  bouyer can_init(void)
     84  1.1.2.1  bouyer {
     85  1.1.2.1  bouyer 	canintrq.ifq_maxlen = canqmaxlen;
     86  1.1.2.1  bouyer 	IFQ_LOCK_INIT(&canintrq);
     87  1.1.2.1  bouyer 	can_pcbinit(&cbtable, canhashsize, canhashsize);
     88  1.1.2.1  bouyer }
     89  1.1.2.1  bouyer 
     90  1.1.2.1  bouyer /*
     91  1.1.2.1  bouyer  * Generic control operations (ioctl's).
     92  1.1.2.1  bouyer  */
     93  1.1.2.7  bouyer static int
     94  1.1.2.7  bouyer can_get_netlink(struct ifnet *ifp, struct ifdrv *ifd)
     95  1.1.2.7  bouyer {
     96  1.1.2.7  bouyer 	struct canif_softc *csc = ifp->if_softc;
     97  1.1.2.7  bouyer 
     98  1.1.2.7  bouyer 	if (ifp->if_dlt != DLT_CAN_SOCKETCAN || csc == NULL)
     99  1.1.2.7  bouyer 		return EOPNOTSUPP;
    100  1.1.2.7  bouyer 
    101  1.1.2.7  bouyer 	switch(ifd->ifd_cmd) {
    102  1.1.2.7  bouyer 	case CANGLINKTIMECAP:
    103  1.1.2.7  bouyer 		if (ifd->ifd_len != sizeof(struct can_link_timecaps))
    104  1.1.2.7  bouyer 			return EINVAL;
    105  1.1.2.7  bouyer 		return copyout(&csc->csc_timecaps, ifd->ifd_data, ifd->ifd_len);
    106  1.1.2.7  bouyer 	case CANGLINKTIMINGS:
    107  1.1.2.7  bouyer 		if (ifd->ifd_len != sizeof(struct can_link_timings))
    108  1.1.2.7  bouyer 			return EINVAL;
    109  1.1.2.7  bouyer 		return copyout(&csc->csc_timings, ifd->ifd_data, ifd->ifd_len);
    110  1.1.2.7  bouyer 	case CANGLINKMODE:
    111  1.1.2.7  bouyer 		if (ifd->ifd_len != sizeof(uint32_t))
    112  1.1.2.7  bouyer 			return EINVAL;
    113  1.1.2.7  bouyer 		return copyout(&csc->csc_linkmodes, ifd->ifd_data, ifd->ifd_len);
    114  1.1.2.7  bouyer 	}
    115  1.1.2.7  bouyer 	return EOPNOTSUPP;
    116  1.1.2.7  bouyer }
    117  1.1.2.7  bouyer 
    118  1.1.2.7  bouyer static int
    119  1.1.2.7  bouyer can_set_netlink(struct ifnet *ifp, struct ifdrv *ifd)
    120  1.1.2.7  bouyer {
    121  1.1.2.7  bouyer 	struct canif_softc *csc = ifp->if_softc;
    122  1.1.2.7  bouyer 	uint32_t mode;
    123  1.1.2.7  bouyer 	int error;
    124  1.1.2.7  bouyer 
    125  1.1.2.7  bouyer 	if (ifp->if_dlt != DLT_CAN_SOCKETCAN || csc == NULL)
    126  1.1.2.7  bouyer 		return EOPNOTSUPP;
    127  1.1.2.7  bouyer 
    128  1.1.2.7  bouyer 	error = kauth_authorize_network(curlwp->l_cred,
    129  1.1.2.7  bouyer 		    KAUTH_NETWORK_INTERFACE,
    130  1.1.2.7  bouyer 		    KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
    131  1.1.2.7  bouyer 	            (void *)SIOCSDRVSPEC, NULL);
    132  1.1.2.7  bouyer 	if (error != 0)
    133  1.1.2.7  bouyer 		return error;
    134  1.1.2.7  bouyer 
    135  1.1.2.7  bouyer 	if ((ifp->if_flags & IFF_UP) != 0) {
    136  1.1.2.7  bouyer 		return EBUSY;
    137  1.1.2.7  bouyer 	}
    138  1.1.2.7  bouyer 
    139  1.1.2.7  bouyer 	switch(ifd->ifd_cmd) {
    140  1.1.2.7  bouyer 	case CANSLINKTIMINGS:
    141  1.1.2.7  bouyer 		if (ifd->ifd_len != sizeof(struct can_link_timings))
    142  1.1.2.7  bouyer 			return EINVAL;
    143  1.1.2.7  bouyer 		return copyin(ifd->ifd_data, &csc->csc_timings, ifd->ifd_len);
    144  1.1.2.7  bouyer 
    145  1.1.2.7  bouyer 	case CANSLINKMODE:
    146  1.1.2.7  bouyer 	case CANCLINKMODE:
    147  1.1.2.7  bouyer 		if (ifd->ifd_len != sizeof(uint32_t))
    148  1.1.2.7  bouyer 			return EINVAL;
    149  1.1.2.7  bouyer 		error = copyout(ifd->ifd_data, &mode, ifd->ifd_len);
    150  1.1.2.7  bouyer 		if (error)
    151  1.1.2.7  bouyer 			return error;
    152  1.1.2.7  bouyer 		if ((mode & csc->csc_timecaps.cltc_linkmode_caps) != mode)
    153  1.1.2.7  bouyer 			return EINVAL;
    154  1.1.2.7  bouyer 		/* XXX locking */
    155  1.1.2.7  bouyer 		if (ifd->ifd_cmd == CANSLINKMODE)
    156  1.1.2.7  bouyer 			csc->csc_linkmodes |= mode;
    157  1.1.2.7  bouyer 		else
    158  1.1.2.7  bouyer 			csc->csc_linkmodes &= ~mode;
    159  1.1.2.7  bouyer 		return 0;
    160  1.1.2.7  bouyer 	}
    161  1.1.2.7  bouyer 	return EOPNOTSUPP;
    162  1.1.2.7  bouyer }
    163  1.1.2.7  bouyer 
    164  1.1.2.1  bouyer /* ARGSUSED */
    165  1.1.2.1  bouyer static int
    166  1.1.2.1  bouyer can_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
    167  1.1.2.1  bouyer {
    168  1.1.2.1  bouyer #if 0
    169  1.1.2.1  bouyer 	struct can_ifreq *cfr = (struct can_ifreq *)data;
    170  1.1.2.1  bouyer 	int error = 0;
    171  1.1.2.1  bouyer #endif
    172  1.1.2.7  bouyer 	if (ifp == NULL)
    173  1.1.2.7  bouyer 		return (EOPNOTSUPP);
    174  1.1.2.1  bouyer 
    175  1.1.2.1  bouyer 	switch (cmd) {
    176  1.1.2.7  bouyer 	case SIOCGDRVSPEC:
    177  1.1.2.7  bouyer 		return can_get_netlink(ifp, (struct ifdrv *) data);
    178  1.1.2.7  bouyer 	case SIOCSDRVSPEC:
    179  1.1.2.7  bouyer 		return can_set_netlink(ifp, (struct ifdrv *) data);
    180  1.1.2.1  bouyer 	default:
    181  1.1.2.7  bouyer 		if (ifp->if_ioctl == 0)
    182  1.1.2.1  bouyer 			return (EOPNOTSUPP);
    183  1.1.2.1  bouyer 		return ((*ifp->if_ioctl)(ifp, cmd, data));
    184  1.1.2.1  bouyer 	}
    185  1.1.2.1  bouyer 	return (0);
    186  1.1.2.1  bouyer }
    187  1.1.2.1  bouyer 
    188  1.1.2.1  bouyer static int
    189  1.1.2.1  bouyer can_purgeif(struct socket *so, struct ifnet *ifp)
    190  1.1.2.1  bouyer {
    191  1.1.2.1  bouyer 	return 0;
    192  1.1.2.1  bouyer }
    193  1.1.2.1  bouyer 
    194  1.1.2.5  bouyer void
    195  1.1.2.5  bouyer can_ifattach(struct ifnet *ifp) {
    196  1.1.2.5  bouyer 	ifp->if_mtu = sizeof(struct can_frame);
    197  1.1.2.5  bouyer 	ifp->if_type = IFT_OTHER;
    198  1.1.2.5  bouyer 	ifp->if_hdrlen = 0;
    199  1.1.2.5  bouyer 	ifp->if_addrlen = 0;
    200  1.1.2.5  bouyer 	ifp->if_dlt = DLT_CAN_SOCKETCAN;
    201  1.1.2.5  bouyer 	ifp->if_output = NULL; /* unused */
    202  1.1.2.5  bouyer 	IFQ_SET_READY(&ifp->if_snd);
    203  1.1.2.9  bouyer 	if_alloc_sadl(ifp);
    204  1.1.2.5  bouyer }
    205  1.1.2.5  bouyer 
    206  1.1.2.8  bouyer void
    207  1.1.2.8  bouyer can_ifinit_timings(struct canif_softc *csc)
    208  1.1.2.8  bouyer {
    209  1.1.2.8  bouyer 	/* uninitialized parameters is all-one */
    210  1.1.2.8  bouyer 	memset(&csc->csc_timings, 0xff, sizeof(struct can_link_timings));
    211  1.1.2.8  bouyer }
    212  1.1.2.8  bouyer 
    213  1.1.2.1  bouyer static int
    214  1.1.2.1  bouyer can_output(struct mbuf *m, struct canpcb *canp)
    215  1.1.2.1  bouyer {
    216  1.1.2.1  bouyer 	struct ifnet *ifp;
    217  1.1.2.1  bouyer 	int error = 0;
    218  1.1.2.2  bouyer 	struct m_tag *sotag;
    219  1.1.2.1  bouyer 
    220  1.1.2.2  bouyer 	if (canp == NULL) {
    221  1.1.2.1  bouyer 		printf("can_output: no pcb\n");
    222  1.1.2.1  bouyer 		error = EINVAL;
    223  1.1.2.2  bouyer 		return error;
    224  1.1.2.1  bouyer 	}
    225  1.1.2.1  bouyer 	ifp = canp->canp_ifp;
    226  1.1.2.1  bouyer 	if (ifp == 0) {
    227  1.1.2.1  bouyer 		error = EDESTADDRREQ;
    228  1.1.2.2  bouyer 		goto bad;
    229  1.1.2.2  bouyer 	}
    230  1.1.2.2  bouyer 	sotag = m_tag_get(PACKET_TAG_SO, sizeof(struct socket *), PR_NOWAIT);
    231  1.1.2.2  bouyer 	if (sotag == NULL) {
    232  1.1.2.2  bouyer 		ifp->if_oerrors++;
    233  1.1.2.2  bouyer 		error = ENOMEM;
    234  1.1.2.2  bouyer 		goto bad;
    235  1.1.2.1  bouyer 	}
    236  1.1.2.2  bouyer 	*(struct socket **)(sotag + 1) = canp->canp_socket;
    237  1.1.2.2  bouyer 	m_tag_prepend(m, sotag);
    238  1.1.2.2  bouyer 
    239  1.1.2.1  bouyer 	if (m->m_len <= ifp->if_mtu) {
    240  1.1.2.1  bouyer 		can_output_cnt++;
    241  1.1.2.5  bouyer 		return ifq_enqueue(ifp, m);
    242  1.1.2.2  bouyer 	} else
    243  1.1.2.2  bouyer 		error = EMSGSIZE;
    244  1.1.2.2  bouyer bad:
    245  1.1.2.1  bouyer 	m_freem(m);
    246  1.1.2.1  bouyer 	return (error);
    247  1.1.2.1  bouyer }
    248  1.1.2.1  bouyer 
    249  1.1.2.1  bouyer /*
    250  1.1.2.4  bouyer  * cleanup mbuf tag, keeping the PACKET_TAG_SO tag
    251  1.1.2.4  bouyer  */
    252  1.1.2.4  bouyer void
    253  1.1.2.4  bouyer can_mbuf_tag_clean(struct mbuf *m)
    254  1.1.2.4  bouyer {
    255  1.1.2.4  bouyer 	struct m_tag *sotag;
    256  1.1.2.4  bouyer 
    257  1.1.2.4  bouyer 	sotag = m_tag_find(m, PACKET_TAG_SO, NULL);
    258  1.1.2.4  bouyer 	m_tag_delete_nonpersistent(m);
    259  1.1.2.4  bouyer 	if (sotag)
    260  1.1.2.4  bouyer 		m_tag_prepend(m, sotag);
    261  1.1.2.4  bouyer }
    262  1.1.2.4  bouyer 
    263  1.1.2.4  bouyer /*
    264  1.1.2.1  bouyer  * Process a received CAN frame
    265  1.1.2.1  bouyer  * the packet is in the mbuf chain m with
    266  1.1.2.1  bouyer  * the CAN header.
    267  1.1.2.1  bouyer  */
    268  1.1.2.1  bouyer void
    269  1.1.2.1  bouyer can_input(struct ifnet *ifp, struct mbuf *m)
    270  1.1.2.1  bouyer {
    271  1.1.2.1  bouyer 	struct ifqueue *inq;
    272  1.1.2.1  bouyer 
    273  1.1.2.1  bouyer 	if ((ifp->if_flags & IFF_UP) == 0) {
    274  1.1.2.1  bouyer 		m_freem(m);
    275  1.1.2.1  bouyer 		return;
    276  1.1.2.1  bouyer 	}
    277  1.1.2.1  bouyer 
    278  1.1.2.1  bouyer 	inq = &canintrq;
    279  1.1.2.1  bouyer 
    280  1.1.2.1  bouyer 	IFQ_LOCK(inq);
    281  1.1.2.1  bouyer 	if (IF_QFULL(inq)) {
    282  1.1.2.1  bouyer 		IF_DROP(inq);
    283  1.1.2.1  bouyer 		IFQ_UNLOCK(inq);
    284  1.1.2.1  bouyer 		m_freem(m);
    285  1.1.2.1  bouyer 	} else {
    286  1.1.2.1  bouyer 		IF_ENQUEUE(inq, m);
    287  1.1.2.1  bouyer 		IFQ_UNLOCK(inq);
    288  1.1.2.1  bouyer 		schednetisr(NETISR_CAN);
    289  1.1.2.1  bouyer 		ifp->if_ipackets++;
    290  1.1.2.1  bouyer 		ifp->if_ibytes += m->m_pkthdr.len;
    291  1.1.2.1  bouyer 	}
    292  1.1.2.1  bouyer }
    293  1.1.2.1  bouyer 
    294  1.1.2.1  bouyer void
    295  1.1.2.1  bouyer canintr(void)
    296  1.1.2.1  bouyer {
    297  1.1.2.1  bouyer 	int		rcv_ifindex;
    298  1.1.2.1  bouyer 	struct mbuf    *m;
    299  1.1.2.1  bouyer 
    300  1.1.2.1  bouyer 	struct sockaddr_can from;
    301  1.1.2.1  bouyer 	struct canpcb   *canp;
    302  1.1.2.2  bouyer 	struct m_tag	*sotag;
    303  1.1.2.2  bouyer 	struct socket	*so;
    304  1.1.2.2  bouyer 	struct canpcb	*sender_canp;
    305  1.1.2.1  bouyer 
    306  1.1.2.1  bouyer 	mutex_enter(softnet_lock);
    307  1.1.2.1  bouyer 	for (;;) {
    308  1.1.2.1  bouyer 		IFQ_LOCK(&canintrq);
    309  1.1.2.1  bouyer 		IF_DEQUEUE(&canintrq, m);
    310  1.1.2.1  bouyer 		IFQ_UNLOCK(&canintrq);
    311  1.1.2.1  bouyer 
    312  1.1.2.2  bouyer 		if (m == NULL)	/* no more queued packets */
    313  1.1.2.1  bouyer 			break;
    314  1.1.2.1  bouyer 
    315  1.1.2.3  bouyer #if 0
    316  1.1.2.3  bouyer 		m_claim(m, &can_rx_mowner);
    317  1.1.2.3  bouyer #endif
    318  1.1.2.2  bouyer 		sotag = m_tag_find(m, PACKET_TAG_SO, NULL);
    319  1.1.2.2  bouyer 		if (sotag) {
    320  1.1.2.2  bouyer 			so = *(struct socket **)(sotag + 1);
    321  1.1.2.2  bouyer 			sender_canp = sotocanpcb(so);
    322  1.1.2.2  bouyer 			m_tag_delete(m, sotag);
    323  1.1.2.2  bouyer 			/* if the sender doesn't want loopback, don't do it */
    324  1.1.2.2  bouyer 			if (sender_canp->canp_flags & CANP_NO_LOOPBACK) {
    325  1.1.2.2  bouyer 				m_freem(m);
    326  1.1.2.2  bouyer 				continue;
    327  1.1.2.2  bouyer 			}
    328  1.1.2.2  bouyer 		} else {
    329  1.1.2.2  bouyer 			sender_canp = NULL;
    330  1.1.2.2  bouyer 		}
    331  1.1.2.1  bouyer 		memset(&from, 0, sizeof(struct sockaddr_can));
    332  1.1.2.1  bouyer 		rcv_ifindex = m->m_pkthdr.rcvif_index;
    333  1.1.2.1  bouyer 		from.can_ifindex = rcv_ifindex;
    334  1.1.2.1  bouyer 		from.can_len = sizeof(struct sockaddr_can);
    335  1.1.2.1  bouyer 		from.can_family = AF_CAN;
    336  1.1.2.1  bouyer 
    337  1.1.2.1  bouyer 		TAILQ_FOREACH(canp, &cbtable.canpt_queue, canp_queue) {
    338  1.1.2.1  bouyer 			struct mbuf *mc;
    339  1.1.2.2  bouyer 
    340  1.1.2.2  bouyer 			/* don't loop back to sockets on other interfaces */
    341  1.1.2.1  bouyer 			if (canp->canp_ifp != NULL &&
    342  1.1.2.1  bouyer 			    canp->canp_ifp->if_index != rcv_ifindex) {
    343  1.1.2.1  bouyer 				continue;
    344  1.1.2.1  bouyer 			}
    345  1.1.2.2  bouyer 			/* don't loop back to myself if I don't want it */
    346  1.1.2.2  bouyer 			if (canp == sender_canp &&
    347  1.1.2.2  bouyer 			    (canp->canp_flags & CANP_RECEIVE_OWN) == 0)
    348  1.1.2.2  bouyer 				continue;
    349  1.1.2.2  bouyer 
    350  1.1.2.3  bouyer 			/* skip if the accept filter doen't match this pkt */
    351  1.1.2.3  bouyer 			if (!can_pcbfilter(canp, m))
    352  1.1.2.3  bouyer 				continue;
    353  1.1.2.3  bouyer 
    354  1.1.2.1  bouyer 			if (TAILQ_NEXT(canp, canp_queue) != NULL) {
    355  1.1.2.1  bouyer 				/*
    356  1.1.2.1  bouyer 				 * we can't be sure we won't need
    357  1.1.2.1  bouyer 				 * the original mbuf later so copy
    358  1.1.2.1  bouyer 				 */
    359  1.1.2.1  bouyer 				mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
    360  1.1.2.1  bouyer 				if (mc == NULL) {
    361  1.1.2.1  bouyer 					/* deliver this mbuf and abort */
    362  1.1.2.1  bouyer 					mc = m;
    363  1.1.2.1  bouyer 					m = NULL;
    364  1.1.2.1  bouyer 				}
    365  1.1.2.1  bouyer 			} else {
    366  1.1.2.1  bouyer 				mc = m;
    367  1.1.2.1  bouyer 				m = NULL;
    368  1.1.2.1  bouyer 			}
    369  1.1.2.1  bouyer 			if (sbappendaddr(&canp->canp_socket->so_rcv,
    370  1.1.2.1  bouyer 					 (struct sockaddr *) &from, mc,
    371  1.1.2.1  bouyer 					 (struct mbuf *) 0) == 0) {
    372  1.1.2.1  bouyer 				m_freem(mc);
    373  1.1.2.1  bouyer 			} else
    374  1.1.2.1  bouyer 				sorwakeup(canp->canp_socket);
    375  1.1.2.1  bouyer 			if (m == NULL)
    376  1.1.2.1  bouyer 				break;
    377  1.1.2.1  bouyer 		}
    378  1.1.2.1  bouyer 		/* If it didn't go anywhere just delete it */
    379  1.1.2.1  bouyer 		if (m) {
    380  1.1.2.1  bouyer 			m_freem(m);
    381  1.1.2.1  bouyer 		}
    382  1.1.2.1  bouyer 	}
    383  1.1.2.1  bouyer 	mutex_exit(softnet_lock);
    384  1.1.2.1  bouyer }
    385  1.1.2.1  bouyer 
    386  1.1.2.1  bouyer static int
    387  1.1.2.1  bouyer can_attach(struct socket *so, int proto)
    388  1.1.2.1  bouyer {
    389  1.1.2.1  bouyer 	int error;
    390  1.1.2.1  bouyer 
    391  1.1.2.1  bouyer 	KASSERT(sotocanpcb(so) == NULL);
    392  1.1.2.1  bouyer 
    393  1.1.2.1  bouyer 	/* Assign the lock (must happen even if we will error out). */
    394  1.1.2.1  bouyer 	sosetlock(so);
    395  1.1.2.1  bouyer 
    396  1.1.2.1  bouyer #ifdef MBUFTRACE
    397  1.1.2.1  bouyer 	so->so_mowner = &can_mowner;
    398  1.1.2.1  bouyer 	so->so_rcv.sb_mowner = &can_rx_mowner;
    399  1.1.2.1  bouyer 	so->so_snd.sb_mowner = &can_tx_mowner;
    400  1.1.2.1  bouyer #endif
    401  1.1.2.1  bouyer 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
    402  1.1.2.1  bouyer 		error = soreserve(so, can_sendspace, can_recvspace);
    403  1.1.2.1  bouyer 		if (error) {
    404  1.1.2.1  bouyer 			return error;
    405  1.1.2.1  bouyer 		}
    406  1.1.2.1  bouyer 	}
    407  1.1.2.1  bouyer 
    408  1.1.2.1  bouyer 	error = can_pcballoc(so, &cbtable);
    409  1.1.2.1  bouyer 	if (error) {
    410  1.1.2.1  bouyer 		return error;
    411  1.1.2.1  bouyer 	}
    412  1.1.2.1  bouyer 	KASSERT(solocked(so));
    413  1.1.2.1  bouyer 
    414  1.1.2.1  bouyer 	return error;
    415  1.1.2.1  bouyer }
    416  1.1.2.1  bouyer 
    417  1.1.2.1  bouyer static void
    418  1.1.2.1  bouyer can_detach(struct socket *so)
    419  1.1.2.1  bouyer {
    420  1.1.2.1  bouyer 	struct canpcb *canp;
    421  1.1.2.1  bouyer 
    422  1.1.2.1  bouyer 	KASSERT(solocked(so));
    423  1.1.2.1  bouyer 	canp = sotocanpcb(so);
    424  1.1.2.1  bouyer 	can_pcbdetach(canp);
    425  1.1.2.1  bouyer }
    426  1.1.2.1  bouyer 
    427  1.1.2.1  bouyer static int
    428  1.1.2.1  bouyer can_accept(struct socket *so, struct sockaddr *nam)
    429  1.1.2.1  bouyer {
    430  1.1.2.1  bouyer 	KASSERT(solocked(so));
    431  1.1.2.1  bouyer 
    432  1.1.2.1  bouyer 	panic("can_accept");
    433  1.1.2.1  bouyer 
    434  1.1.2.1  bouyer 	return EOPNOTSUPP;
    435  1.1.2.1  bouyer }
    436  1.1.2.1  bouyer 
    437  1.1.2.1  bouyer static int
    438  1.1.2.1  bouyer can_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
    439  1.1.2.1  bouyer {
    440  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    441  1.1.2.1  bouyer 	struct sockaddr_can *scan = (struct sockaddr_can *)nam;
    442  1.1.2.1  bouyer 
    443  1.1.2.1  bouyer 	KASSERT(solocked(so));
    444  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    445  1.1.2.1  bouyer 
    446  1.1.2.1  bouyer 	return can_pcbbind(canp, scan, l);
    447  1.1.2.1  bouyer }
    448  1.1.2.1  bouyer 
    449  1.1.2.1  bouyer static int
    450  1.1.2.1  bouyer can_listen(struct socket *so, struct lwp *l)
    451  1.1.2.1  bouyer {
    452  1.1.2.1  bouyer 	KASSERT(solocked(so));
    453  1.1.2.1  bouyer 
    454  1.1.2.1  bouyer 	return EOPNOTSUPP;
    455  1.1.2.1  bouyer }
    456  1.1.2.1  bouyer 
    457  1.1.2.1  bouyer static int
    458  1.1.2.1  bouyer can_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
    459  1.1.2.1  bouyer {
    460  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    461  1.1.2.1  bouyer 	int error = 0;
    462  1.1.2.1  bouyer 
    463  1.1.2.1  bouyer 	KASSERT(solocked(so));
    464  1.1.2.1  bouyer 	KASSERT(canp != NULL);
    465  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    466  1.1.2.1  bouyer 
    467  1.1.2.1  bouyer 	error = can_pcbconnect(canp, (struct sockaddr_can *)nam);
    468  1.1.2.1  bouyer 	if (! error)
    469  1.1.2.1  bouyer 		soisconnected(so);
    470  1.1.2.1  bouyer 	return error;
    471  1.1.2.1  bouyer }
    472  1.1.2.1  bouyer 
    473  1.1.2.1  bouyer static int
    474  1.1.2.1  bouyer can_connect2(struct socket *so, struct socket *so2)
    475  1.1.2.1  bouyer {
    476  1.1.2.1  bouyer 	KASSERT(solocked(so));
    477  1.1.2.1  bouyer 
    478  1.1.2.1  bouyer 	return EOPNOTSUPP;
    479  1.1.2.1  bouyer }
    480  1.1.2.1  bouyer 
    481  1.1.2.1  bouyer static int
    482  1.1.2.1  bouyer can_disconnect(struct socket *so)
    483  1.1.2.1  bouyer {
    484  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    485  1.1.2.1  bouyer 
    486  1.1.2.1  bouyer 	KASSERT(solocked(so));
    487  1.1.2.1  bouyer 	KASSERT(canp != NULL);
    488  1.1.2.1  bouyer 
    489  1.1.2.1  bouyer 	/*soisdisconnected(so);*/
    490  1.1.2.1  bouyer 	so->so_state &= ~SS_ISCONNECTED;	/* XXX */
    491  1.1.2.1  bouyer 	can_pcbdisconnect(canp);
    492  1.1.2.1  bouyer 	can_pcbstate(canp, CANP_BOUND);		/* XXX */
    493  1.1.2.1  bouyer 	return 0;
    494  1.1.2.1  bouyer }
    495  1.1.2.1  bouyer 
    496  1.1.2.1  bouyer static int
    497  1.1.2.1  bouyer can_shutdown(struct socket *so)
    498  1.1.2.1  bouyer {
    499  1.1.2.1  bouyer 	KASSERT(solocked(so));
    500  1.1.2.1  bouyer 
    501  1.1.2.1  bouyer 	socantsendmore(so);
    502  1.1.2.1  bouyer 	return 0;
    503  1.1.2.1  bouyer }
    504  1.1.2.1  bouyer 
    505  1.1.2.1  bouyer static int
    506  1.1.2.1  bouyer can_abort(struct socket *so)
    507  1.1.2.1  bouyer {
    508  1.1.2.1  bouyer 	KASSERT(solocked(so));
    509  1.1.2.1  bouyer 
    510  1.1.2.1  bouyer 	panic("can_abort");
    511  1.1.2.1  bouyer 
    512  1.1.2.1  bouyer 	return EOPNOTSUPP;
    513  1.1.2.1  bouyer }
    514  1.1.2.1  bouyer 
    515  1.1.2.1  bouyer static int
    516  1.1.2.1  bouyer can_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
    517  1.1.2.1  bouyer {
    518  1.1.2.1  bouyer 	return can_control(so, cmd, nam, ifp);
    519  1.1.2.1  bouyer }
    520  1.1.2.1  bouyer 
    521  1.1.2.1  bouyer static int
    522  1.1.2.1  bouyer can_stat(struct socket *so, struct stat *ub)
    523  1.1.2.1  bouyer {
    524  1.1.2.1  bouyer 	KASSERT(solocked(so));
    525  1.1.2.1  bouyer 
    526  1.1.2.1  bouyer 	/* stat: don't bother with a blocksize. */
    527  1.1.2.1  bouyer 	return 0;
    528  1.1.2.1  bouyer }
    529  1.1.2.1  bouyer 
    530  1.1.2.1  bouyer static int
    531  1.1.2.1  bouyer can_peeraddr(struct socket *so, struct sockaddr *nam)
    532  1.1.2.1  bouyer {
    533  1.1.2.1  bouyer 	KASSERT(solocked(so));
    534  1.1.2.1  bouyer 	KASSERT(sotocanpcb(so) != NULL);
    535  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    536  1.1.2.1  bouyer 
    537  1.1.2.1  bouyer 	return EOPNOTSUPP;
    538  1.1.2.1  bouyer }
    539  1.1.2.1  bouyer 
    540  1.1.2.1  bouyer static int
    541  1.1.2.1  bouyer can_sockaddr(struct socket *so, struct sockaddr *nam)
    542  1.1.2.1  bouyer {
    543  1.1.2.1  bouyer 	KASSERT(solocked(so));
    544  1.1.2.1  bouyer 	KASSERT(sotocanpcb(so) != NULL);
    545  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    546  1.1.2.1  bouyer 
    547  1.1.2.1  bouyer 	can_setsockaddr(sotocanpcb(so), (struct sockaddr_can *)nam);
    548  1.1.2.1  bouyer 
    549  1.1.2.1  bouyer 	return 0;
    550  1.1.2.1  bouyer }
    551  1.1.2.1  bouyer 
    552  1.1.2.1  bouyer static int
    553  1.1.2.1  bouyer can_rcvd(struct socket *so, int flags, struct lwp *l)
    554  1.1.2.1  bouyer {
    555  1.1.2.1  bouyer 	KASSERT(solocked(so));
    556  1.1.2.1  bouyer 
    557  1.1.2.1  bouyer 	return EOPNOTSUPP;
    558  1.1.2.1  bouyer }
    559  1.1.2.1  bouyer 
    560  1.1.2.1  bouyer static int
    561  1.1.2.1  bouyer can_recvoob(struct socket *so, struct mbuf *m, int flags)
    562  1.1.2.1  bouyer {
    563  1.1.2.1  bouyer 	KASSERT(solocked(so));
    564  1.1.2.1  bouyer 
    565  1.1.2.1  bouyer 	return EOPNOTSUPP;
    566  1.1.2.1  bouyer }
    567  1.1.2.1  bouyer 
    568  1.1.2.1  bouyer static int
    569  1.1.2.1  bouyer can_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
    570  1.1.2.1  bouyer     struct mbuf *control, struct lwp *l)
    571  1.1.2.1  bouyer {
    572  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    573  1.1.2.1  bouyer 	int error = 0;
    574  1.1.2.1  bouyer 	int s;
    575  1.1.2.1  bouyer 
    576  1.1.2.1  bouyer 	if (control && control->m_len) {
    577  1.1.2.1  bouyer 		return EINVAL;
    578  1.1.2.1  bouyer 	}
    579  1.1.2.6  bouyer 	if (m->m_len > sizeof(struct can_frame) ||
    580  1.1.2.6  bouyer 	   m->m_len < offsetof(struct can_frame, can_dlc))
    581  1.1.2.6  bouyer 		return EINVAL;
    582  1.1.2.6  bouyer 
    583  1.1.2.6  bouyer 	/* we expect all data in the first mbuf */
    584  1.1.2.6  bouyer 	KASSERT((m->m_flags & M_PKTHDR) != 0);
    585  1.1.2.6  bouyer 	KASSERT(m->m_len == m->m_pkthdr.len);
    586  1.1.2.1  bouyer 
    587  1.1.2.1  bouyer 	if (nam) {
    588  1.1.2.1  bouyer 		if ((so->so_state & SS_ISCONNECTED) != 0) {
    589  1.1.2.1  bouyer 			return EISCONN;
    590  1.1.2.1  bouyer 		}
    591  1.1.2.1  bouyer 		s = splnet();
    592  1.1.2.1  bouyer 		error = can_pcbbind(canp, (struct sockaddr_can *)nam, l);
    593  1.1.2.1  bouyer 		if (error) {
    594  1.1.2.1  bouyer 			splx(s);
    595  1.1.2.1  bouyer 			return error;
    596  1.1.2.1  bouyer 		}
    597  1.1.2.1  bouyer 	} else {
    598  1.1.2.1  bouyer 		if ((so->so_state & SS_ISCONNECTED) == 0) {
    599  1.1.2.1  bouyer 			return EDESTADDRREQ;
    600  1.1.2.1  bouyer 		}
    601  1.1.2.1  bouyer 	}
    602  1.1.2.1  bouyer 	error = can_output(m, canp);
    603  1.1.2.1  bouyer 	if (nam) {
    604  1.1.2.1  bouyer 		struct sockaddr_can lscan;
    605  1.1.2.1  bouyer 		memset(&lscan, 0, sizeof(lscan));
    606  1.1.2.1  bouyer 		lscan.can_family = AF_CAN;
    607  1.1.2.1  bouyer 		lscan.can_len = sizeof(lscan);
    608  1.1.2.1  bouyer 		can_pcbbind(canp, &lscan, l);
    609  1.1.2.1  bouyer 	}
    610  1.1.2.1  bouyer 	return error;
    611  1.1.2.1  bouyer }
    612  1.1.2.1  bouyer 
    613  1.1.2.1  bouyer static int
    614  1.1.2.1  bouyer can_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
    615  1.1.2.1  bouyer {
    616  1.1.2.1  bouyer 	KASSERT(solocked(so));
    617  1.1.2.1  bouyer 
    618  1.1.2.1  bouyer 	m_freem(m);
    619  1.1.2.1  bouyer 	m_freem(control);
    620  1.1.2.1  bouyer 
    621  1.1.2.1  bouyer 	return EOPNOTSUPP;
    622  1.1.2.1  bouyer }
    623  1.1.2.1  bouyer 
    624  1.1.2.1  bouyer #if 0
    625  1.1.2.1  bouyer int
    626  1.1.2.1  bouyer can_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
    627  1.1.2.1  bouyer 	   struct mbuf *control, struct lwp *l)
    628  1.1.2.1  bouyer {
    629  1.1.2.1  bouyer 	struct canpcb *canp;
    630  1.1.2.1  bouyer 	int s;
    631  1.1.2.1  bouyer 	int error = 0;
    632  1.1.2.1  bouyer 
    633  1.1.2.1  bouyer 	if (req == PRU_CONTROL)
    634  1.1.2.1  bouyer 		 return (can_control(so, (long)m, nam,
    635  1.1.2.1  bouyer 		     (struct ifnet *)control));
    636  1.1.2.1  bouyer 
    637  1.1.2.1  bouyer 	if (req == PRU_PURGEIF) {
    638  1.1.2.1  bouyer #if 0
    639  1.1.2.1  bouyer 		can_pcbpurgeif0(&udbtable, (struct ifnet *)control);
    640  1.1.2.1  bouyer 		can_purgeif((struct ifnet *)control);
    641  1.1.2.1  bouyer 		can_pcbpurgeif(&udbtable, (struct ifnet *)control);
    642  1.1.2.1  bouyer #endif
    643  1.1.2.1  bouyer 		return (0);
    644  1.1.2.1  bouyer 	}
    645  1.1.2.1  bouyer 
    646  1.1.2.1  bouyer 	s = splsoftnet();
    647  1.1.2.1  bouyer 	canp = sotocanpcb(so);
    648  1.1.2.1  bouyer #ifdef DIAGNOSTIC
    649  1.1.2.1  bouyer 	if (req != PRU_SEND && req != PRU_SENDOOB && control)
    650  1.1.2.1  bouyer 		panic("can_usrreq: unexpected control mbuf");
    651  1.1.2.1  bouyer #endif
    652  1.1.2.1  bouyer 	if (canp == 0 && req != PRU_ATTACH) {
    653  1.1.2.1  bouyer 		printf("can_usrreq: no pcb %p %d\n", canp, req);
    654  1.1.2.1  bouyer 		error = EINVAL;
    655  1.1.2.1  bouyer 		goto release;
    656  1.1.2.1  bouyer 	}
    657  1.1.2.1  bouyer 
    658  1.1.2.1  bouyer 	/*
    659  1.1.2.1  bouyer 	 * Note: need to block can_input while changing
    660  1.1.2.1  bouyer 	 * the can pcb queue and/or pcb addresses.
    661  1.1.2.1  bouyer 	 */
    662  1.1.2.1  bouyer 	switch (req) {
    663  1.1.2.1  bouyer 
    664  1.1.2.1  bouyer 	  case PRU_ATTACH:
    665  1.1.2.1  bouyer 	      if (canp != 0) {
    666  1.1.2.1  bouyer 			 error = EISCONN;
    667  1.1.2.1  bouyer 			 break;
    668  1.1.2.1  bouyer 		 }
    669  1.1.2.1  bouyer #ifdef MBUFTRACE
    670  1.1.2.1  bouyer 		so->so_mowner = &can_mowner;
    671  1.1.2.1  bouyer 		so->so_rcv.sb_mowner = &can_rx_mowner;
    672  1.1.2.1  bouyer 		so->so_snd.sb_mowner = &can_tx_mowner;
    673  1.1.2.1  bouyer #endif
    674  1.1.2.1  bouyer 		if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
    675  1.1.2.1  bouyer 			error = soreserve(so, can_sendspace, can_recvspace);
    676  1.1.2.1  bouyer 			if (error)
    677  1.1.2.1  bouyer 				break;
    678  1.1.2.1  bouyer 		}
    679  1.1.2.1  bouyer 		error = can_pcballoc(so, &cbtable);
    680  1.1.2.1  bouyer 		if (error)
    681  1.1.2.1  bouyer 			break;
    682  1.1.2.1  bouyer 		canp = sotocanpcb(so);
    683  1.1.2.1  bouyer #if 0
    684  1.1.2.1  bouyer 		inp->inp_ip.ip_ttl = ip_defttl;
    685  1.1.2.1  bouyer #endif
    686  1.1.2.1  bouyer 		break;
    687  1.1.2.1  bouyer 
    688  1.1.2.1  bouyer 	case PRU_DETACH:
    689  1.1.2.1  bouyer 		can_pcbdetach(canp);
    690  1.1.2.1  bouyer 		break;
    691  1.1.2.1  bouyer 
    692  1.1.2.1  bouyer 	case PRU_BIND:
    693  1.1.2.1  bouyer 		error = can_pcbbind(canp, nam, l);
    694  1.1.2.1  bouyer 		break;
    695  1.1.2.1  bouyer 
    696  1.1.2.1  bouyer 	case PRU_LISTEN:
    697  1.1.2.1  bouyer 		error = EOPNOTSUPP;
    698  1.1.2.1  bouyer 		break;
    699  1.1.2.1  bouyer 
    700  1.1.2.1  bouyer 	case PRU_CONNECT:
    701  1.1.2.1  bouyer 		error = can_pcbconnect(canp, nam);
    702  1.1.2.1  bouyer 		if (error)
    703  1.1.2.1  bouyer 			break;
    704  1.1.2.1  bouyer 		soisconnected(so);
    705  1.1.2.1  bouyer 		break;
    706  1.1.2.1  bouyer 
    707  1.1.2.1  bouyer 	case PRU_CONNECT2:
    708  1.1.2.1  bouyer 		error = EOPNOTSUPP;
    709  1.1.2.1  bouyer 		break;
    710  1.1.2.1  bouyer 
    711  1.1.2.1  bouyer 	case PRU_DISCONNECT:
    712  1.1.2.1  bouyer 		/*soisdisconnected(so);*/
    713  1.1.2.1  bouyer 		so->so_state &= ~SS_ISCONNECTED;	/* XXX */
    714  1.1.2.1  bouyer 		can_pcbdisconnect(canp);
    715  1.1.2.1  bouyer 		can_pcbstate(canp, CANP_BOUND);		/* XXX */
    716  1.1.2.1  bouyer 		break;
    717  1.1.2.1  bouyer 
    718  1.1.2.1  bouyer 	case PRU_SHUTDOWN:
    719  1.1.2.1  bouyer 		socantsendmore(so);
    720  1.1.2.1  bouyer 		break;
    721  1.1.2.1  bouyer 
    722  1.1.2.1  bouyer 	case PRU_RCVD:
    723  1.1.2.1  bouyer 		error = EOPNOTSUPP;
    724  1.1.2.1  bouyer 		break;
    725  1.1.2.1  bouyer 
    726  1.1.2.1  bouyer 	case PRU_SEND:
    727  1.1.2.1  bouyer 		break;
    728  1.1.2.1  bouyer 
    729  1.1.2.1  bouyer 	case PRU_SENSE:
    730  1.1.2.1  bouyer 		/*
    731  1.1.2.1  bouyer 		 * stat: don't bother with a blocksize.
    732  1.1.2.1  bouyer 		 */
    733  1.1.2.1  bouyer 		splx(s);
    734  1.1.2.1  bouyer 		return (0);
    735  1.1.2.1  bouyer 
    736  1.1.2.1  bouyer 	case PRU_RCVOOB:
    737  1.1.2.1  bouyer 		error =  EOPNOTSUPP;
    738  1.1.2.1  bouyer 		break;
    739  1.1.2.1  bouyer 
    740  1.1.2.1  bouyer 	case PRU_SENDOOB:
    741  1.1.2.1  bouyer 		m_freem(control);
    742  1.1.2.1  bouyer 		m_freem(m);
    743  1.1.2.1  bouyer 		error =  EOPNOTSUPP;
    744  1.1.2.1  bouyer 		break;
    745  1.1.2.1  bouyer 
    746  1.1.2.1  bouyer 	case PRU_SOCKADDR:
    747  1.1.2.1  bouyer 
    748  1.1.2.1  bouyer 		break;
    749  1.1.2.1  bouyer 
    750  1.1.2.1  bouyer 	case PRU_PEERADDR:
    751  1.1.2.1  bouyer 		error =  EOPNOTSUPP;
    752  1.1.2.1  bouyer 		break;
    753  1.1.2.1  bouyer 
    754  1.1.2.1  bouyer 	default:
    755  1.1.2.1  bouyer 		panic("can_usrreq");
    756  1.1.2.1  bouyer 	}
    757  1.1.2.1  bouyer 
    758  1.1.2.1  bouyer release:
    759  1.1.2.1  bouyer 	splx(s);
    760  1.1.2.1  bouyer 	return (error);
    761  1.1.2.1  bouyer }
    762  1.1.2.1  bouyer #endif
    763  1.1.2.1  bouyer 
    764  1.1.2.1  bouyer #if 0
    765  1.1.2.1  bouyer static void
    766  1.1.2.1  bouyer can_notify(struct canpcb *canp, int errno)
    767  1.1.2.1  bouyer {
    768  1.1.2.1  bouyer 
    769  1.1.2.1  bouyer 	canp->canp_socket->so_error = errno;
    770  1.1.2.1  bouyer 	sorwakeup(canp->canp_socket);
    771  1.1.2.1  bouyer 	sowwakeup(canp->canp_socket);
    772  1.1.2.1  bouyer }
    773  1.1.2.1  bouyer 
    774  1.1.2.1  bouyer void *
    775  1.1.2.1  bouyer can_ctlinput(int cmd, struct sockaddr *sa, void *v)
    776  1.1.2.1  bouyer {
    777  1.1.2.1  bouyer 	struct ip *ip = v;
    778  1.1.2.1  bouyer 	struct canhdr *uh;
    779  1.1.2.1  bouyer 	void (*notify) __P((struct inpcb *, int)) = can_notify;
    780  1.1.2.1  bouyer 	int errno;
    781  1.1.2.1  bouyer 
    782  1.1.2.1  bouyer 	if (sa->sa_family != AF_CAN
    783  1.1.2.1  bouyer 	 || sa->sa_len != sizeof(struct sockaddr_can))
    784  1.1.2.1  bouyer 		return NULL;
    785  1.1.2.1  bouyer 	if ((unsigned)cmd >= PRC_NCMDS)
    786  1.1.2.1  bouyer 		return NULL;
    787  1.1.2.1  bouyer 	errno = inetctlerrmap[cmd];
    788  1.1.2.1  bouyer 	if (PRC_IS_REDIRECT(cmd))
    789  1.1.2.1  bouyer 		notify = in_rtchange, ip = 0;
    790  1.1.2.1  bouyer 	else if (cmd == PRC_HOSTDEAD)
    791  1.1.2.1  bouyer 		ip = 0;
    792  1.1.2.1  bouyer 	else if (errno == 0)
    793  1.1.2.1  bouyer 		return NULL;
    794  1.1.2.1  bouyer 	if (ip) {
    795  1.1.2.1  bouyer 		uh = (struct canhdr *)((caddr_t)ip + (ip->ip_hl << 2));
    796  1.1.2.1  bouyer 		in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport,
    797  1.1.2.1  bouyer 		    ip->ip_src, uh->uh_sport, errno, notify);
    798  1.1.2.1  bouyer 
    799  1.1.2.1  bouyer 		/* XXX mapped address case */
    800  1.1.2.1  bouyer 	} else
    801  1.1.2.1  bouyer 		can_pcbnotifyall(&cbtable, satoscan(sa)->scan_addr, errno,
    802  1.1.2.1  bouyer 		    notify);
    803  1.1.2.1  bouyer 	return NULL;
    804  1.1.2.1  bouyer }
    805  1.1.2.1  bouyer #endif
    806  1.1.2.1  bouyer 
    807  1.1.2.2  bouyer static int
    808  1.1.2.2  bouyer can_raw_getop(struct canpcb *canp, struct sockopt *sopt)
    809  1.1.2.2  bouyer {
    810  1.1.2.2  bouyer 	int optval = 0;
    811  1.1.2.2  bouyer 	int error;
    812  1.1.2.2  bouyer 
    813  1.1.2.2  bouyer 	switch (sopt->sopt_name) {
    814  1.1.2.2  bouyer 	case CAN_RAW_LOOPBACK:
    815  1.1.2.2  bouyer 		optval = (canp->canp_flags & CANP_NO_LOOPBACK) ? 0 : 1;
    816  1.1.2.2  bouyer 		error = sockopt_set(sopt, &optval, sizeof(optval));
    817  1.1.2.2  bouyer 		break;
    818  1.1.2.2  bouyer 	case CAN_RAW_RECV_OWN_MSGS:
    819  1.1.2.2  bouyer 		optval = (canp->canp_flags & CANP_RECEIVE_OWN) ? 1 : 0;
    820  1.1.2.2  bouyer 		error = sockopt_set(sopt, &optval, sizeof(optval));
    821  1.1.2.2  bouyer 		break;
    822  1.1.2.3  bouyer 	case CAN_RAW_FILTER:
    823  1.1.2.3  bouyer 		error = sockopt_set(sopt, canp->canp_filters,
    824  1.1.2.3  bouyer 		    sizeof(struct can_filter) * canp->canp_nfilters);
    825  1.1.2.3  bouyer 		break;
    826  1.1.2.2  bouyer 	default:
    827  1.1.2.2  bouyer 		error = ENOPROTOOPT;
    828  1.1.2.2  bouyer 		break;
    829  1.1.2.2  bouyer 	}
    830  1.1.2.2  bouyer 	return error;
    831  1.1.2.2  bouyer }
    832  1.1.2.2  bouyer 
    833  1.1.2.2  bouyer static int
    834  1.1.2.2  bouyer can_raw_setop(struct canpcb *canp, struct sockopt *sopt)
    835  1.1.2.2  bouyer {
    836  1.1.2.2  bouyer 	int optval = 0;
    837  1.1.2.2  bouyer 	int error;
    838  1.1.2.2  bouyer 
    839  1.1.2.2  bouyer 	switch (sopt->sopt_name) {
    840  1.1.2.2  bouyer 	case CAN_RAW_LOOPBACK:
    841  1.1.2.2  bouyer 		error = sockopt_getint(sopt, &optval);
    842  1.1.2.2  bouyer 		if (error == 0) {
    843  1.1.2.2  bouyer 			if (optval) {
    844  1.1.2.2  bouyer 				canp->canp_flags &= ~CANP_NO_LOOPBACK;
    845  1.1.2.2  bouyer 			} else {
    846  1.1.2.2  bouyer 				canp->canp_flags |= CANP_NO_LOOPBACK;
    847  1.1.2.2  bouyer 			}
    848  1.1.2.2  bouyer 		}
    849  1.1.2.2  bouyer 		break;
    850  1.1.2.2  bouyer 	case CAN_RAW_RECV_OWN_MSGS:
    851  1.1.2.2  bouyer 		error = sockopt_getint(sopt, &optval);
    852  1.1.2.2  bouyer 		if (error == 0) {
    853  1.1.2.2  bouyer 			if (optval) {
    854  1.1.2.2  bouyer 				canp->canp_flags |= CANP_RECEIVE_OWN;
    855  1.1.2.2  bouyer 			} else {
    856  1.1.2.2  bouyer 				canp->canp_flags &= ~CANP_RECEIVE_OWN;
    857  1.1.2.2  bouyer 			}
    858  1.1.2.2  bouyer 		}
    859  1.1.2.2  bouyer 		break;
    860  1.1.2.3  bouyer 	case CAN_RAW_FILTER:
    861  1.1.2.3  bouyer 		{
    862  1.1.2.3  bouyer 		int nfilters = sopt->sopt_size / sizeof(struct can_filter);
    863  1.1.2.3  bouyer 		if (sopt->sopt_size % sizeof(struct can_filter) != 0)
    864  1.1.2.3  bouyer 			return EINVAL;
    865  1.1.2.3  bouyer 		error = can_pcbsetfilter(canp, sopt->sopt_data, nfilters);
    866  1.1.2.3  bouyer 		break;
    867  1.1.2.3  bouyer 		}
    868  1.1.2.2  bouyer 	default:
    869  1.1.2.2  bouyer 		error = ENOPROTOOPT;
    870  1.1.2.2  bouyer 		break;
    871  1.1.2.2  bouyer 	}
    872  1.1.2.2  bouyer 	return error;
    873  1.1.2.2  bouyer }
    874  1.1.2.2  bouyer 
    875  1.1.2.2  bouyer /*
    876  1.1.2.2  bouyer  * Called by getsockopt and setsockopt.
    877  1.1.2.2  bouyer  *
    878  1.1.2.2  bouyer  */
    879  1.1.2.2  bouyer int
    880  1.1.2.2  bouyer can_ctloutput(int op, struct socket *so, struct sockopt *sopt)
    881  1.1.2.2  bouyer {
    882  1.1.2.2  bouyer 	struct canpcb *canp;
    883  1.1.2.2  bouyer 	int error;
    884  1.1.2.2  bouyer 	int s;
    885  1.1.2.2  bouyer 
    886  1.1.2.2  bouyer 	if (so->so_proto->pr_domain->dom_family != PF_CAN)
    887  1.1.2.2  bouyer 		return EAFNOSUPPORT;
    888  1.1.2.2  bouyer 
    889  1.1.2.2  bouyer 	if (sopt->sopt_level != SOL_CAN_RAW)
    890  1.1.2.2  bouyer 		return EINVAL;
    891  1.1.2.2  bouyer 
    892  1.1.2.2  bouyer 	s = splsoftnet();
    893  1.1.2.2  bouyer 	canp = sotocanpcb(so);
    894  1.1.2.2  bouyer 	if (canp == NULL) {
    895  1.1.2.2  bouyer 		splx(s);
    896  1.1.2.2  bouyer 		return ECONNRESET;
    897  1.1.2.2  bouyer 	}
    898  1.1.2.2  bouyer 
    899  1.1.2.2  bouyer 	if (op == PRCO_SETOPT) {
    900  1.1.2.2  bouyer 		error = can_raw_setop(canp, sopt);
    901  1.1.2.2  bouyer 	} else if (op ==  PRCO_GETOPT) {
    902  1.1.2.2  bouyer 		error = can_raw_getop(canp, sopt);
    903  1.1.2.2  bouyer 	} else {
    904  1.1.2.2  bouyer 		error = EINVAL;
    905  1.1.2.2  bouyer 	}
    906  1.1.2.2  bouyer 	splx(s);
    907  1.1.2.2  bouyer 	return error;
    908  1.1.2.2  bouyer }
    909  1.1.2.2  bouyer 
    910  1.1.2.1  bouyer PR_WRAP_USRREQS(can)
    911  1.1.2.1  bouyer #define	can_attach	can_attach_wrapper
    912  1.1.2.1  bouyer #define	can_detach	can_detach_wrapper
    913  1.1.2.1  bouyer #define	can_accept	can_accept_wrapper
    914  1.1.2.1  bouyer #define	can_bind	can_bind_wrapper
    915  1.1.2.1  bouyer #define	can_listen	can_listen_wrapper
    916  1.1.2.1  bouyer #define	can_connect	can_connect_wrapper
    917  1.1.2.1  bouyer #define	can_connect2	can_connect2_wrapper
    918  1.1.2.1  bouyer #define	can_disconnect	can_disconnect_wrapper
    919  1.1.2.1  bouyer #define	can_shutdown	can_shutdown_wrapper
    920  1.1.2.1  bouyer #define	can_abort	can_abort_wrapper
    921  1.1.2.1  bouyer #define	can_ioctl	can_ioctl_wrapper
    922  1.1.2.1  bouyer #define	can_stat	can_stat_wrapper
    923  1.1.2.1  bouyer #define	can_peeraddr	can_peeraddr_wrapper
    924  1.1.2.1  bouyer #define	can_sockaddr	can_sockaddr_wrapper
    925  1.1.2.1  bouyer #define	can_rcvd	can_rcvd_wrapper
    926  1.1.2.1  bouyer #define	can_recvoob	can_recvoob_wrapper
    927  1.1.2.1  bouyer #define	can_send	can_send_wrapper
    928  1.1.2.1  bouyer #define	can_sendoob	can_sendoob_wrapper
    929  1.1.2.1  bouyer #define	can_purgeif	can_purgeif_wrapper
    930  1.1.2.1  bouyer 
    931  1.1.2.1  bouyer const struct pr_usrreqs can_usrreqs = {
    932  1.1.2.1  bouyer 	.pr_attach	= can_attach,
    933  1.1.2.1  bouyer 	.pr_detach	= can_detach,
    934  1.1.2.1  bouyer 	.pr_accept	= can_accept,
    935  1.1.2.1  bouyer 	.pr_bind	= can_bind,
    936  1.1.2.1  bouyer 	.pr_listen	= can_listen,
    937  1.1.2.1  bouyer 	.pr_connect	= can_connect,
    938  1.1.2.1  bouyer 	.pr_connect2	= can_connect2,
    939  1.1.2.1  bouyer 	.pr_disconnect	= can_disconnect,
    940  1.1.2.1  bouyer 	.pr_shutdown	= can_shutdown,
    941  1.1.2.1  bouyer 	.pr_abort	= can_abort,
    942  1.1.2.1  bouyer 	.pr_ioctl	= can_ioctl,
    943  1.1.2.1  bouyer 	.pr_stat	= can_stat,
    944  1.1.2.1  bouyer 	.pr_peeraddr	= can_peeraddr,
    945  1.1.2.1  bouyer 	.pr_sockaddr	= can_sockaddr,
    946  1.1.2.1  bouyer 	.pr_rcvd	= can_rcvd,
    947  1.1.2.1  bouyer 	.pr_recvoob	= can_recvoob,
    948  1.1.2.1  bouyer 	.pr_send	= can_send,
    949  1.1.2.1  bouyer 	.pr_sendoob	= can_sendoob,
    950  1.1.2.1  bouyer 	.pr_purgeif	= can_purgeif,
    951  1.1.2.1  bouyer };
    952