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