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