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