Home | History | Annotate | Line # | Download | only in netcan
can.c revision 1.1.2.1
      1  1.1.2.1  bouyer /*	$NetBSD: can.c,v 1.1.2.1 2017/01/15 20:27:33 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.1  bouyer __KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.1 2017/01/15 20:27:33 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.1  bouyer #include <sys/protosw.h>
     40  1.1.2.1  bouyer #include <sys/errno.h>
     41  1.1.2.1  bouyer #include <sys/socket.h>
     42  1.1.2.1  bouyer #include <sys/socketvar.h>
     43  1.1.2.1  bouyer #include <sys/proc.h>
     44  1.1.2.1  bouyer #include <sys/kauth.h>
     45  1.1.2.1  bouyer 
     46  1.1.2.1  bouyer #include <net/if.h>
     47  1.1.2.1  bouyer #include <net/netisr.h>
     48  1.1.2.1  bouyer #include <net/route.h>
     49  1.1.2.1  bouyer 
     50  1.1.2.1  bouyer #include <netcan/can.h>
     51  1.1.2.1  bouyer #include <netcan/can_pcb.h>
     52  1.1.2.1  bouyer #include <netcan/can_var.h>
     53  1.1.2.1  bouyer 
     54  1.1.2.1  bouyer struct canpcb canpcb;
     55  1.1.2.1  bouyer #if 0
     56  1.1.2.1  bouyer struct canpcb canrawpcb;
     57  1.1.2.1  bouyer #endif
     58  1.1.2.1  bouyer 
     59  1.1.2.1  bouyer struct	canpcbtable cbtable;
     60  1.1.2.1  bouyer 
     61  1.1.2.1  bouyer struct ifqueue	canintrq;
     62  1.1.2.1  bouyer int	canqmaxlen = IFQ_MAXLEN;
     63  1.1.2.1  bouyer 
     64  1.1.2.1  bouyer int can_copy_output = 0;
     65  1.1.2.1  bouyer int can_output_cnt = 0;
     66  1.1.2.1  bouyer struct mbuf *can_lastout;
     67  1.1.2.1  bouyer 
     68  1.1.2.1  bouyer int	can_sendspace = 4096;		/* really max datagram size */
     69  1.1.2.1  bouyer int	can_recvspace = 40 * (1024 + sizeof(struct sockaddr_can));
     70  1.1.2.1  bouyer 					/* 40 1K datagrams */
     71  1.1.2.1  bouyer #ifndef CANHASHSIZE
     72  1.1.2.1  bouyer #define	CANHASHSIZE	128
     73  1.1.2.1  bouyer #endif
     74  1.1.2.1  bouyer int	canhashsize = CANHASHSIZE;
     75  1.1.2.1  bouyer 
     76  1.1.2.1  bouyer static int can_output(struct mbuf *, struct canpcb *);
     77  1.1.2.1  bouyer 
     78  1.1.2.1  bouyer static int can_control(struct socket *, u_long, void *, struct ifnet *);
     79  1.1.2.1  bouyer 
     80  1.1.2.1  bouyer void
     81  1.1.2.1  bouyer can_init(void)
     82  1.1.2.1  bouyer {
     83  1.1.2.1  bouyer 	canintrq.ifq_maxlen = canqmaxlen;
     84  1.1.2.1  bouyer 	IFQ_LOCK_INIT(&canintrq);
     85  1.1.2.1  bouyer 	can_pcbinit(&cbtable, canhashsize, canhashsize);
     86  1.1.2.1  bouyer }
     87  1.1.2.1  bouyer 
     88  1.1.2.1  bouyer /*
     89  1.1.2.1  bouyer  * Generic control operations (ioctl's).
     90  1.1.2.1  bouyer  */
     91  1.1.2.1  bouyer /* ARGSUSED */
     92  1.1.2.1  bouyer static int
     93  1.1.2.1  bouyer can_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
     94  1.1.2.1  bouyer {
     95  1.1.2.1  bouyer #if 0
     96  1.1.2.1  bouyer 	struct can_ifreq *cfr = (struct can_ifreq *)data;
     97  1.1.2.1  bouyer 	int error = 0;
     98  1.1.2.1  bouyer #endif
     99  1.1.2.1  bouyer 
    100  1.1.2.1  bouyer 
    101  1.1.2.1  bouyer 	switch (cmd) {
    102  1.1.2.1  bouyer 
    103  1.1.2.1  bouyer 	default:
    104  1.1.2.1  bouyer 		if (ifp == 0 || ifp->if_ioctl == 0)
    105  1.1.2.1  bouyer 			return (EOPNOTSUPP);
    106  1.1.2.1  bouyer 		return ((*ifp->if_ioctl)(ifp, cmd, data));
    107  1.1.2.1  bouyer 	}
    108  1.1.2.1  bouyer 	return (0);
    109  1.1.2.1  bouyer }
    110  1.1.2.1  bouyer 
    111  1.1.2.1  bouyer static int
    112  1.1.2.1  bouyer can_purgeif(struct socket *so, struct ifnet *ifp)
    113  1.1.2.1  bouyer {
    114  1.1.2.1  bouyer 	return 0;
    115  1.1.2.1  bouyer }
    116  1.1.2.1  bouyer 
    117  1.1.2.1  bouyer static int
    118  1.1.2.1  bouyer can_output(struct mbuf *m, struct canpcb *canp)
    119  1.1.2.1  bouyer {
    120  1.1.2.1  bouyer 	struct ifnet *ifp;
    121  1.1.2.1  bouyer 	int error = 0;
    122  1.1.2.1  bouyer 
    123  1.1.2.1  bouyer 	if (canp == 0) {
    124  1.1.2.1  bouyer 		printf("can_output: no pcb\n");
    125  1.1.2.1  bouyer 		error = EINVAL;
    126  1.1.2.1  bouyer 		goto done;
    127  1.1.2.1  bouyer 	}
    128  1.1.2.1  bouyer 	ifp = canp->canp_ifp;
    129  1.1.2.1  bouyer 	if (ifp == 0) {
    130  1.1.2.1  bouyer 		error = EDESTADDRREQ;
    131  1.1.2.1  bouyer 		goto done;
    132  1.1.2.1  bouyer 	}
    133  1.1.2.1  bouyer 	if (m->m_len <= ifp->if_mtu) {
    134  1.1.2.1  bouyer 		can_output_cnt++;
    135  1.1.2.1  bouyer 		error = (*ifp->if_output)(ifp, m, NULL, 0);
    136  1.1.2.1  bouyer 		goto done;
    137  1.1.2.1  bouyer 	} else error = EMSGSIZE;
    138  1.1.2.1  bouyer 
    139  1.1.2.1  bouyer 	m_freem(m);
    140  1.1.2.1  bouyer done:
    141  1.1.2.1  bouyer 	return (error);
    142  1.1.2.1  bouyer }
    143  1.1.2.1  bouyer 
    144  1.1.2.1  bouyer /*
    145  1.1.2.1  bouyer  * Process a received CAN frame
    146  1.1.2.1  bouyer  * the packet is in the mbuf chain m with
    147  1.1.2.1  bouyer  * the CAN header.
    148  1.1.2.1  bouyer  */
    149  1.1.2.1  bouyer void
    150  1.1.2.1  bouyer can_input(struct ifnet *ifp, struct mbuf *m)
    151  1.1.2.1  bouyer {
    152  1.1.2.1  bouyer 	struct ifqueue *inq;
    153  1.1.2.1  bouyer 
    154  1.1.2.1  bouyer 	if ((ifp->if_flags & IFF_UP) == 0) {
    155  1.1.2.1  bouyer 		m_freem(m);
    156  1.1.2.1  bouyer 		return;
    157  1.1.2.1  bouyer 	}
    158  1.1.2.1  bouyer 
    159  1.1.2.1  bouyer 	inq = &canintrq;
    160  1.1.2.1  bouyer 
    161  1.1.2.1  bouyer 	IFQ_LOCK(inq);
    162  1.1.2.1  bouyer 	if (IF_QFULL(inq)) {
    163  1.1.2.1  bouyer 		IF_DROP(inq);
    164  1.1.2.1  bouyer 		IFQ_UNLOCK(inq);
    165  1.1.2.1  bouyer 		m_freem(m);
    166  1.1.2.1  bouyer 	} else {
    167  1.1.2.1  bouyer 		IF_ENQUEUE(inq, m);
    168  1.1.2.1  bouyer 		IFQ_UNLOCK(inq);
    169  1.1.2.1  bouyer 		schednetisr(NETISR_CAN);
    170  1.1.2.1  bouyer 		ifp->if_ipackets++;
    171  1.1.2.1  bouyer 		ifp->if_ibytes += m->m_pkthdr.len;
    172  1.1.2.1  bouyer 	}
    173  1.1.2.1  bouyer }
    174  1.1.2.1  bouyer 
    175  1.1.2.1  bouyer void
    176  1.1.2.1  bouyer canintr(void)
    177  1.1.2.1  bouyer {
    178  1.1.2.1  bouyer 	int		rcv_ifindex;
    179  1.1.2.1  bouyer 	struct mbuf    *m;
    180  1.1.2.1  bouyer 
    181  1.1.2.1  bouyer 	struct sockaddr_can from;
    182  1.1.2.1  bouyer 	struct canpcb   *canp;
    183  1.1.2.1  bouyer 
    184  1.1.2.1  bouyer 	mutex_enter(softnet_lock);
    185  1.1.2.1  bouyer 	for (;;) {
    186  1.1.2.1  bouyer 		IFQ_LOCK(&canintrq);
    187  1.1.2.1  bouyer 		IF_DEQUEUE(&canintrq, m);
    188  1.1.2.1  bouyer 		IFQ_UNLOCK(&canintrq);
    189  1.1.2.1  bouyer 
    190  1.1.2.1  bouyer 		if (m == 0)	/* no more queued packets */
    191  1.1.2.1  bouyer 			break;
    192  1.1.2.1  bouyer 
    193  1.1.2.1  bouyer 		memset(&from, 0, sizeof(struct sockaddr_can));
    194  1.1.2.1  bouyer 		rcv_ifindex = m->m_pkthdr.rcvif_index;
    195  1.1.2.1  bouyer #if 0
    196  1.1.2.1  bouyer 		m_claim(m, &can_rx_mowner);
    197  1.1.2.1  bouyer #endif
    198  1.1.2.1  bouyer 		from.can_ifindex = rcv_ifindex;
    199  1.1.2.1  bouyer 		from.can_len = sizeof(struct sockaddr_can);
    200  1.1.2.1  bouyer 		from.can_family = AF_CAN;
    201  1.1.2.1  bouyer 
    202  1.1.2.1  bouyer 		TAILQ_FOREACH(canp, &cbtable.canpt_queue, canp_queue) {
    203  1.1.2.1  bouyer 			struct mbuf *mc;
    204  1.1.2.1  bouyer 			if (canp->canp_ifp != NULL &&
    205  1.1.2.1  bouyer 			    canp->canp_ifp->if_index != rcv_ifindex) {
    206  1.1.2.1  bouyer 				continue;
    207  1.1.2.1  bouyer 			}
    208  1.1.2.1  bouyer 			if (TAILQ_NEXT(canp, canp_queue) != NULL) {
    209  1.1.2.1  bouyer 				/*
    210  1.1.2.1  bouyer 				 * we can't be sure we won't need
    211  1.1.2.1  bouyer 				 * the original mbuf later so copy
    212  1.1.2.1  bouyer 				 */
    213  1.1.2.1  bouyer 				mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
    214  1.1.2.1  bouyer 				if (mc == NULL) {
    215  1.1.2.1  bouyer 					/* deliver this mbuf and abort */
    216  1.1.2.1  bouyer 					mc = m;
    217  1.1.2.1  bouyer 					m = NULL;
    218  1.1.2.1  bouyer 				}
    219  1.1.2.1  bouyer 			} else {
    220  1.1.2.1  bouyer 				mc = m;
    221  1.1.2.1  bouyer 				m = NULL;
    222  1.1.2.1  bouyer 			}
    223  1.1.2.1  bouyer 			if (sbappendaddr(&canp->canp_socket->so_rcv,
    224  1.1.2.1  bouyer 					 (struct sockaddr *) &from, mc,
    225  1.1.2.1  bouyer 					 (struct mbuf *) 0) == 0) {
    226  1.1.2.1  bouyer 				m_freem(mc);
    227  1.1.2.1  bouyer 			} else
    228  1.1.2.1  bouyer 				sorwakeup(canp->canp_socket);
    229  1.1.2.1  bouyer 			if (m == NULL)
    230  1.1.2.1  bouyer 				break;
    231  1.1.2.1  bouyer 		}
    232  1.1.2.1  bouyer 		/* If it didn't go anywhere just delete it */
    233  1.1.2.1  bouyer 		if (m) {
    234  1.1.2.1  bouyer 			m_freem(m);
    235  1.1.2.1  bouyer 		}
    236  1.1.2.1  bouyer 	}
    237  1.1.2.1  bouyer 	mutex_exit(softnet_lock);
    238  1.1.2.1  bouyer }
    239  1.1.2.1  bouyer 
    240  1.1.2.1  bouyer static int
    241  1.1.2.1  bouyer can_attach(struct socket *so, int proto)
    242  1.1.2.1  bouyer {
    243  1.1.2.1  bouyer 	/*struct canpcb *canp;*/
    244  1.1.2.1  bouyer 	int error;
    245  1.1.2.1  bouyer 
    246  1.1.2.1  bouyer 	KASSERT(sotocanpcb(so) == NULL);
    247  1.1.2.1  bouyer 
    248  1.1.2.1  bouyer 	/* Assign the lock (must happen even if we will error out). */
    249  1.1.2.1  bouyer 	sosetlock(so);
    250  1.1.2.1  bouyer 
    251  1.1.2.1  bouyer #ifdef MBUFTRACE
    252  1.1.2.1  bouyer 	so->so_mowner = &can_mowner;
    253  1.1.2.1  bouyer 	so->so_rcv.sb_mowner = &can_rx_mowner;
    254  1.1.2.1  bouyer 	so->so_snd.sb_mowner = &can_tx_mowner;
    255  1.1.2.1  bouyer #endif
    256  1.1.2.1  bouyer 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
    257  1.1.2.1  bouyer 		error = soreserve(so, can_sendspace, can_recvspace);
    258  1.1.2.1  bouyer 		if (error) {
    259  1.1.2.1  bouyer 			return error;
    260  1.1.2.1  bouyer 		}
    261  1.1.2.1  bouyer 	}
    262  1.1.2.1  bouyer 
    263  1.1.2.1  bouyer 	error = can_pcballoc(so, &cbtable);
    264  1.1.2.1  bouyer 	if (error) {
    265  1.1.2.1  bouyer 		return error;
    266  1.1.2.1  bouyer 	}
    267  1.1.2.1  bouyer 	/*canp = sotocanpcb(so);*/
    268  1.1.2.1  bouyer 	KASSERT(solocked(so));
    269  1.1.2.1  bouyer 
    270  1.1.2.1  bouyer 	return error;
    271  1.1.2.1  bouyer }
    272  1.1.2.1  bouyer 
    273  1.1.2.1  bouyer static void
    274  1.1.2.1  bouyer can_detach(struct socket *so)
    275  1.1.2.1  bouyer {
    276  1.1.2.1  bouyer 	struct canpcb *canp;
    277  1.1.2.1  bouyer 
    278  1.1.2.1  bouyer 	KASSERT(solocked(so));
    279  1.1.2.1  bouyer 	canp = sotocanpcb(so);
    280  1.1.2.1  bouyer 	can_pcbdetach(canp);
    281  1.1.2.1  bouyer }
    282  1.1.2.1  bouyer 
    283  1.1.2.1  bouyer static int
    284  1.1.2.1  bouyer can_accept(struct socket *so, struct sockaddr *nam)
    285  1.1.2.1  bouyer {
    286  1.1.2.1  bouyer 	KASSERT(solocked(so));
    287  1.1.2.1  bouyer 
    288  1.1.2.1  bouyer 	panic("can_accept");
    289  1.1.2.1  bouyer 
    290  1.1.2.1  bouyer 	return EOPNOTSUPP;
    291  1.1.2.1  bouyer }
    292  1.1.2.1  bouyer 
    293  1.1.2.1  bouyer static int
    294  1.1.2.1  bouyer can_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
    295  1.1.2.1  bouyer {
    296  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    297  1.1.2.1  bouyer 	struct sockaddr_can *scan = (struct sockaddr_can *)nam;
    298  1.1.2.1  bouyer 
    299  1.1.2.1  bouyer 	KASSERT(solocked(so));
    300  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    301  1.1.2.1  bouyer 
    302  1.1.2.1  bouyer 	return can_pcbbind(canp, scan, l);
    303  1.1.2.1  bouyer }
    304  1.1.2.1  bouyer 
    305  1.1.2.1  bouyer static int
    306  1.1.2.1  bouyer can_listen(struct socket *so, struct lwp *l)
    307  1.1.2.1  bouyer {
    308  1.1.2.1  bouyer 	KASSERT(solocked(so));
    309  1.1.2.1  bouyer 
    310  1.1.2.1  bouyer 	return EOPNOTSUPP;
    311  1.1.2.1  bouyer }
    312  1.1.2.1  bouyer 
    313  1.1.2.1  bouyer static int
    314  1.1.2.1  bouyer can_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
    315  1.1.2.1  bouyer {
    316  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    317  1.1.2.1  bouyer 	int error = 0;
    318  1.1.2.1  bouyer 
    319  1.1.2.1  bouyer 	KASSERT(solocked(so));
    320  1.1.2.1  bouyer 	KASSERT(canp != NULL);
    321  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    322  1.1.2.1  bouyer 
    323  1.1.2.1  bouyer 	error = can_pcbconnect(canp, (struct sockaddr_can *)nam);
    324  1.1.2.1  bouyer 	if (! error)
    325  1.1.2.1  bouyer 		soisconnected(so);
    326  1.1.2.1  bouyer 	return error;
    327  1.1.2.1  bouyer }
    328  1.1.2.1  bouyer 
    329  1.1.2.1  bouyer static int
    330  1.1.2.1  bouyer can_connect2(struct socket *so, struct socket *so2)
    331  1.1.2.1  bouyer {
    332  1.1.2.1  bouyer 	KASSERT(solocked(so));
    333  1.1.2.1  bouyer 
    334  1.1.2.1  bouyer 	return EOPNOTSUPP;
    335  1.1.2.1  bouyer }
    336  1.1.2.1  bouyer 
    337  1.1.2.1  bouyer static int
    338  1.1.2.1  bouyer can_disconnect(struct socket *so)
    339  1.1.2.1  bouyer {
    340  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    341  1.1.2.1  bouyer 
    342  1.1.2.1  bouyer 	KASSERT(solocked(so));
    343  1.1.2.1  bouyer 	KASSERT(canp != NULL);
    344  1.1.2.1  bouyer 
    345  1.1.2.1  bouyer 	/*soisdisconnected(so);*/
    346  1.1.2.1  bouyer 	so->so_state &= ~SS_ISCONNECTED;	/* XXX */
    347  1.1.2.1  bouyer 	can_pcbdisconnect(canp);
    348  1.1.2.1  bouyer 	can_pcbstate(canp, CANP_BOUND);		/* XXX */
    349  1.1.2.1  bouyer 	return 0;
    350  1.1.2.1  bouyer }
    351  1.1.2.1  bouyer 
    352  1.1.2.1  bouyer static int
    353  1.1.2.1  bouyer can_shutdown(struct socket *so)
    354  1.1.2.1  bouyer {
    355  1.1.2.1  bouyer 	KASSERT(solocked(so));
    356  1.1.2.1  bouyer 
    357  1.1.2.1  bouyer 	socantsendmore(so);
    358  1.1.2.1  bouyer 	return 0;
    359  1.1.2.1  bouyer }
    360  1.1.2.1  bouyer 
    361  1.1.2.1  bouyer static int
    362  1.1.2.1  bouyer can_abort(struct socket *so)
    363  1.1.2.1  bouyer {
    364  1.1.2.1  bouyer 	KASSERT(solocked(so));
    365  1.1.2.1  bouyer 
    366  1.1.2.1  bouyer 	panic("can_abort");
    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_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
    373  1.1.2.1  bouyer {
    374  1.1.2.1  bouyer 	return can_control(so, cmd, nam, ifp);
    375  1.1.2.1  bouyer }
    376  1.1.2.1  bouyer 
    377  1.1.2.1  bouyer static int
    378  1.1.2.1  bouyer can_stat(struct socket *so, struct stat *ub)
    379  1.1.2.1  bouyer {
    380  1.1.2.1  bouyer 	KASSERT(solocked(so));
    381  1.1.2.1  bouyer 
    382  1.1.2.1  bouyer 	/* stat: don't bother with a blocksize. */
    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_peeraddr(struct socket *so, struct sockaddr *nam)
    388  1.1.2.1  bouyer {
    389  1.1.2.1  bouyer 	KASSERT(solocked(so));
    390  1.1.2.1  bouyer 	KASSERT(sotocanpcb(so) != NULL);
    391  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    392  1.1.2.1  bouyer 
    393  1.1.2.1  bouyer 	return EOPNOTSUPP;
    394  1.1.2.1  bouyer }
    395  1.1.2.1  bouyer 
    396  1.1.2.1  bouyer static int
    397  1.1.2.1  bouyer can_sockaddr(struct socket *so, struct sockaddr *nam)
    398  1.1.2.1  bouyer {
    399  1.1.2.1  bouyer 	KASSERT(solocked(so));
    400  1.1.2.1  bouyer 	KASSERT(sotocanpcb(so) != NULL);
    401  1.1.2.1  bouyer 	KASSERT(nam != NULL);
    402  1.1.2.1  bouyer 
    403  1.1.2.1  bouyer 	can_setsockaddr(sotocanpcb(so), (struct sockaddr_can *)nam);
    404  1.1.2.1  bouyer 
    405  1.1.2.1  bouyer 	return 0;
    406  1.1.2.1  bouyer }
    407  1.1.2.1  bouyer 
    408  1.1.2.1  bouyer static int
    409  1.1.2.1  bouyer can_rcvd(struct socket *so, int flags, struct lwp *l)
    410  1.1.2.1  bouyer {
    411  1.1.2.1  bouyer 	KASSERT(solocked(so));
    412  1.1.2.1  bouyer 
    413  1.1.2.1  bouyer 	return EOPNOTSUPP;
    414  1.1.2.1  bouyer }
    415  1.1.2.1  bouyer 
    416  1.1.2.1  bouyer static int
    417  1.1.2.1  bouyer can_recvoob(struct socket *so, struct mbuf *m, int flags)
    418  1.1.2.1  bouyer {
    419  1.1.2.1  bouyer 	KASSERT(solocked(so));
    420  1.1.2.1  bouyer 
    421  1.1.2.1  bouyer 	return EOPNOTSUPP;
    422  1.1.2.1  bouyer }
    423  1.1.2.1  bouyer 
    424  1.1.2.1  bouyer static int
    425  1.1.2.1  bouyer can_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
    426  1.1.2.1  bouyer     struct mbuf *control, struct lwp *l)
    427  1.1.2.1  bouyer {
    428  1.1.2.1  bouyer 	struct canpcb *canp = sotocanpcb(so);
    429  1.1.2.1  bouyer 	int error = 0;
    430  1.1.2.1  bouyer 	int s;
    431  1.1.2.1  bouyer 
    432  1.1.2.1  bouyer 	if (control && control->m_len) {
    433  1.1.2.1  bouyer 		return EINVAL;
    434  1.1.2.1  bouyer 	}
    435  1.1.2.1  bouyer 
    436  1.1.2.1  bouyer 	if (nam) {
    437  1.1.2.1  bouyer 		if ((so->so_state & SS_ISCONNECTED) != 0) {
    438  1.1.2.1  bouyer 			return EISCONN;
    439  1.1.2.1  bouyer 		}
    440  1.1.2.1  bouyer 		s = splnet();
    441  1.1.2.1  bouyer 		error = can_pcbbind(canp, (struct sockaddr_can *)nam, l);
    442  1.1.2.1  bouyer 		if (error) {
    443  1.1.2.1  bouyer 			splx(s);
    444  1.1.2.1  bouyer 			return error;
    445  1.1.2.1  bouyer 		}
    446  1.1.2.1  bouyer 	} else {
    447  1.1.2.1  bouyer 		if ((so->so_state & SS_ISCONNECTED) == 0) {
    448  1.1.2.1  bouyer 			return EDESTADDRREQ;
    449  1.1.2.1  bouyer 		}
    450  1.1.2.1  bouyer 	}
    451  1.1.2.1  bouyer 	error = can_output(m, canp);
    452  1.1.2.1  bouyer 	if (nam) {
    453  1.1.2.1  bouyer 		struct sockaddr_can lscan;
    454  1.1.2.1  bouyer 		memset(&lscan, 0, sizeof(lscan));
    455  1.1.2.1  bouyer 		lscan.can_family = AF_CAN;
    456  1.1.2.1  bouyer 		lscan.can_len = sizeof(lscan);
    457  1.1.2.1  bouyer 		can_pcbbind(canp, &lscan, l);
    458  1.1.2.1  bouyer 	}
    459  1.1.2.1  bouyer 	return error;
    460  1.1.2.1  bouyer }
    461  1.1.2.1  bouyer 
    462  1.1.2.1  bouyer static int
    463  1.1.2.1  bouyer can_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
    464  1.1.2.1  bouyer {
    465  1.1.2.1  bouyer 	KASSERT(solocked(so));
    466  1.1.2.1  bouyer 
    467  1.1.2.1  bouyer 	m_freem(m);
    468  1.1.2.1  bouyer 	m_freem(control);
    469  1.1.2.1  bouyer 
    470  1.1.2.1  bouyer 	return EOPNOTSUPP;
    471  1.1.2.1  bouyer }
    472  1.1.2.1  bouyer 
    473  1.1.2.1  bouyer #if 0
    474  1.1.2.1  bouyer int
    475  1.1.2.1  bouyer can_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
    476  1.1.2.1  bouyer 	   struct mbuf *control, struct lwp *l)
    477  1.1.2.1  bouyer {
    478  1.1.2.1  bouyer 	struct canpcb *canp;
    479  1.1.2.1  bouyer 	int s;
    480  1.1.2.1  bouyer 	int error = 0;
    481  1.1.2.1  bouyer 
    482  1.1.2.1  bouyer 	if (req == PRU_CONTROL)
    483  1.1.2.1  bouyer 		 return (can_control(so, (long)m, nam,
    484  1.1.2.1  bouyer 		     (struct ifnet *)control));
    485  1.1.2.1  bouyer 
    486  1.1.2.1  bouyer 	if (req == PRU_PURGEIF) {
    487  1.1.2.1  bouyer #if 0
    488  1.1.2.1  bouyer 		can_pcbpurgeif0(&udbtable, (struct ifnet *)control);
    489  1.1.2.1  bouyer 		can_purgeif((struct ifnet *)control);
    490  1.1.2.1  bouyer 		can_pcbpurgeif(&udbtable, (struct ifnet *)control);
    491  1.1.2.1  bouyer #endif
    492  1.1.2.1  bouyer 		return (0);
    493  1.1.2.1  bouyer 	}
    494  1.1.2.1  bouyer 
    495  1.1.2.1  bouyer 	s = splsoftnet();
    496  1.1.2.1  bouyer 	canp = sotocanpcb(so);
    497  1.1.2.1  bouyer #ifdef DIAGNOSTIC
    498  1.1.2.1  bouyer 	if (req != PRU_SEND && req != PRU_SENDOOB && control)
    499  1.1.2.1  bouyer 		panic("can_usrreq: unexpected control mbuf");
    500  1.1.2.1  bouyer #endif
    501  1.1.2.1  bouyer 	if (canp == 0 && req != PRU_ATTACH) {
    502  1.1.2.1  bouyer 		printf("can_usrreq: no pcb %p %d\n", canp, req);
    503  1.1.2.1  bouyer 		error = EINVAL;
    504  1.1.2.1  bouyer 		goto release;
    505  1.1.2.1  bouyer 	}
    506  1.1.2.1  bouyer 
    507  1.1.2.1  bouyer 	/*
    508  1.1.2.1  bouyer 	 * Note: need to block can_input while changing
    509  1.1.2.1  bouyer 	 * the can pcb queue and/or pcb addresses.
    510  1.1.2.1  bouyer 	 */
    511  1.1.2.1  bouyer 	switch (req) {
    512  1.1.2.1  bouyer 
    513  1.1.2.1  bouyer 	  case PRU_ATTACH:
    514  1.1.2.1  bouyer 	      if (canp != 0) {
    515  1.1.2.1  bouyer 			 error = EISCONN;
    516  1.1.2.1  bouyer 			 break;
    517  1.1.2.1  bouyer 		 }
    518  1.1.2.1  bouyer #ifdef MBUFTRACE
    519  1.1.2.1  bouyer 		so->so_mowner = &can_mowner;
    520  1.1.2.1  bouyer 		so->so_rcv.sb_mowner = &can_rx_mowner;
    521  1.1.2.1  bouyer 		so->so_snd.sb_mowner = &can_tx_mowner;
    522  1.1.2.1  bouyer #endif
    523  1.1.2.1  bouyer 		if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
    524  1.1.2.1  bouyer 			error = soreserve(so, can_sendspace, can_recvspace);
    525  1.1.2.1  bouyer 			if (error)
    526  1.1.2.1  bouyer 				break;
    527  1.1.2.1  bouyer 		}
    528  1.1.2.1  bouyer 		error = can_pcballoc(so, &cbtable);
    529  1.1.2.1  bouyer 		if (error)
    530  1.1.2.1  bouyer 			break;
    531  1.1.2.1  bouyer 		canp = sotocanpcb(so);
    532  1.1.2.1  bouyer #if 0
    533  1.1.2.1  bouyer 		inp->inp_ip.ip_ttl = ip_defttl;
    534  1.1.2.1  bouyer #endif
    535  1.1.2.1  bouyer 		break;
    536  1.1.2.1  bouyer 
    537  1.1.2.1  bouyer 	case PRU_DETACH:
    538  1.1.2.1  bouyer 		can_pcbdetach(canp);
    539  1.1.2.1  bouyer 		break;
    540  1.1.2.1  bouyer 
    541  1.1.2.1  bouyer 	case PRU_BIND:
    542  1.1.2.1  bouyer 		error = can_pcbbind(canp, nam, l);
    543  1.1.2.1  bouyer 		break;
    544  1.1.2.1  bouyer 
    545  1.1.2.1  bouyer 	case PRU_LISTEN:
    546  1.1.2.1  bouyer 		error = EOPNOTSUPP;
    547  1.1.2.1  bouyer 		break;
    548  1.1.2.1  bouyer 
    549  1.1.2.1  bouyer 	case PRU_CONNECT:
    550  1.1.2.1  bouyer 		error = can_pcbconnect(canp, nam);
    551  1.1.2.1  bouyer 		if (error)
    552  1.1.2.1  bouyer 			break;
    553  1.1.2.1  bouyer 		soisconnected(so);
    554  1.1.2.1  bouyer 		break;
    555  1.1.2.1  bouyer 
    556  1.1.2.1  bouyer 	case PRU_CONNECT2:
    557  1.1.2.1  bouyer 		error = EOPNOTSUPP;
    558  1.1.2.1  bouyer 		break;
    559  1.1.2.1  bouyer 
    560  1.1.2.1  bouyer 	case PRU_DISCONNECT:
    561  1.1.2.1  bouyer 		/*soisdisconnected(so);*/
    562  1.1.2.1  bouyer 		so->so_state &= ~SS_ISCONNECTED;	/* XXX */
    563  1.1.2.1  bouyer 		can_pcbdisconnect(canp);
    564  1.1.2.1  bouyer 		can_pcbstate(canp, CANP_BOUND);		/* XXX */
    565  1.1.2.1  bouyer 		break;
    566  1.1.2.1  bouyer 
    567  1.1.2.1  bouyer 	case PRU_SHUTDOWN:
    568  1.1.2.1  bouyer 		socantsendmore(so);
    569  1.1.2.1  bouyer 		break;
    570  1.1.2.1  bouyer 
    571  1.1.2.1  bouyer 	case PRU_RCVD:
    572  1.1.2.1  bouyer 		error = EOPNOTSUPP;
    573  1.1.2.1  bouyer 		break;
    574  1.1.2.1  bouyer 
    575  1.1.2.1  bouyer 	case PRU_SEND:
    576  1.1.2.1  bouyer 		break;
    577  1.1.2.1  bouyer 
    578  1.1.2.1  bouyer 	case PRU_SENSE:
    579  1.1.2.1  bouyer 		/*
    580  1.1.2.1  bouyer 		 * stat: don't bother with a blocksize.
    581  1.1.2.1  bouyer 		 */
    582  1.1.2.1  bouyer 		splx(s);
    583  1.1.2.1  bouyer 		return (0);
    584  1.1.2.1  bouyer 
    585  1.1.2.1  bouyer 	case PRU_RCVOOB:
    586  1.1.2.1  bouyer 		error =  EOPNOTSUPP;
    587  1.1.2.1  bouyer 		break;
    588  1.1.2.1  bouyer 
    589  1.1.2.1  bouyer 	case PRU_SENDOOB:
    590  1.1.2.1  bouyer 		m_freem(control);
    591  1.1.2.1  bouyer 		m_freem(m);
    592  1.1.2.1  bouyer 		error =  EOPNOTSUPP;
    593  1.1.2.1  bouyer 		break;
    594  1.1.2.1  bouyer 
    595  1.1.2.1  bouyer 	case PRU_SOCKADDR:
    596  1.1.2.1  bouyer 
    597  1.1.2.1  bouyer 		break;
    598  1.1.2.1  bouyer 
    599  1.1.2.1  bouyer 	case PRU_PEERADDR:
    600  1.1.2.1  bouyer 		error =  EOPNOTSUPP;
    601  1.1.2.1  bouyer 		break;
    602  1.1.2.1  bouyer 
    603  1.1.2.1  bouyer 	default:
    604  1.1.2.1  bouyer 		panic("can_usrreq");
    605  1.1.2.1  bouyer 	}
    606  1.1.2.1  bouyer 
    607  1.1.2.1  bouyer release:
    608  1.1.2.1  bouyer 	splx(s);
    609  1.1.2.1  bouyer 	return (error);
    610  1.1.2.1  bouyer }
    611  1.1.2.1  bouyer #endif
    612  1.1.2.1  bouyer 
    613  1.1.2.1  bouyer #if 0
    614  1.1.2.1  bouyer static void
    615  1.1.2.1  bouyer can_notify(struct canpcb *canp, int errno)
    616  1.1.2.1  bouyer {
    617  1.1.2.1  bouyer 
    618  1.1.2.1  bouyer 	canp->canp_socket->so_error = errno;
    619  1.1.2.1  bouyer 	sorwakeup(canp->canp_socket);
    620  1.1.2.1  bouyer 	sowwakeup(canp->canp_socket);
    621  1.1.2.1  bouyer }
    622  1.1.2.1  bouyer 
    623  1.1.2.1  bouyer void *
    624  1.1.2.1  bouyer can_ctlinput(int cmd, struct sockaddr *sa, void *v)
    625  1.1.2.1  bouyer {
    626  1.1.2.1  bouyer 	struct ip *ip = v;
    627  1.1.2.1  bouyer 	struct canhdr *uh;
    628  1.1.2.1  bouyer 	void (*notify) __P((struct inpcb *, int)) = can_notify;
    629  1.1.2.1  bouyer 	int errno;
    630  1.1.2.1  bouyer 
    631  1.1.2.1  bouyer 	if (sa->sa_family != AF_CAN
    632  1.1.2.1  bouyer 	 || sa->sa_len != sizeof(struct sockaddr_can))
    633  1.1.2.1  bouyer 		return NULL;
    634  1.1.2.1  bouyer 	if ((unsigned)cmd >= PRC_NCMDS)
    635  1.1.2.1  bouyer 		return NULL;
    636  1.1.2.1  bouyer 	errno = inetctlerrmap[cmd];
    637  1.1.2.1  bouyer 	if (PRC_IS_REDIRECT(cmd))
    638  1.1.2.1  bouyer 		notify = in_rtchange, ip = 0;
    639  1.1.2.1  bouyer 	else if (cmd == PRC_HOSTDEAD)
    640  1.1.2.1  bouyer 		ip = 0;
    641  1.1.2.1  bouyer 	else if (errno == 0)
    642  1.1.2.1  bouyer 		return NULL;
    643  1.1.2.1  bouyer 	if (ip) {
    644  1.1.2.1  bouyer 		uh = (struct canhdr *)((caddr_t)ip + (ip->ip_hl << 2));
    645  1.1.2.1  bouyer 		in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport,
    646  1.1.2.1  bouyer 		    ip->ip_src, uh->uh_sport, errno, notify);
    647  1.1.2.1  bouyer 
    648  1.1.2.1  bouyer 		/* XXX mapped address case */
    649  1.1.2.1  bouyer 	} else
    650  1.1.2.1  bouyer 		can_pcbnotifyall(&cbtable, satoscan(sa)->scan_addr, errno,
    651  1.1.2.1  bouyer 		    notify);
    652  1.1.2.1  bouyer 	return NULL;
    653  1.1.2.1  bouyer }
    654  1.1.2.1  bouyer #endif
    655  1.1.2.1  bouyer 
    656  1.1.2.1  bouyer PR_WRAP_USRREQS(can)
    657  1.1.2.1  bouyer #define	can_attach	can_attach_wrapper
    658  1.1.2.1  bouyer #define	can_detach	can_detach_wrapper
    659  1.1.2.1  bouyer #define	can_accept	can_accept_wrapper
    660  1.1.2.1  bouyer #define	can_bind	can_bind_wrapper
    661  1.1.2.1  bouyer #define	can_listen	can_listen_wrapper
    662  1.1.2.1  bouyer #define	can_connect	can_connect_wrapper
    663  1.1.2.1  bouyer #define	can_connect2	can_connect2_wrapper
    664  1.1.2.1  bouyer #define	can_disconnect	can_disconnect_wrapper
    665  1.1.2.1  bouyer #define	can_shutdown	can_shutdown_wrapper
    666  1.1.2.1  bouyer #define	can_abort	can_abort_wrapper
    667  1.1.2.1  bouyer #define	can_ioctl	can_ioctl_wrapper
    668  1.1.2.1  bouyer #define	can_stat	can_stat_wrapper
    669  1.1.2.1  bouyer #define	can_peeraddr	can_peeraddr_wrapper
    670  1.1.2.1  bouyer #define	can_sockaddr	can_sockaddr_wrapper
    671  1.1.2.1  bouyer #define	can_rcvd	can_rcvd_wrapper
    672  1.1.2.1  bouyer #define	can_recvoob	can_recvoob_wrapper
    673  1.1.2.1  bouyer #define	can_send	can_send_wrapper
    674  1.1.2.1  bouyer #define	can_sendoob	can_sendoob_wrapper
    675  1.1.2.1  bouyer #define	can_purgeif	can_purgeif_wrapper
    676  1.1.2.1  bouyer 
    677  1.1.2.1  bouyer const struct pr_usrreqs can_usrreqs = {
    678  1.1.2.1  bouyer 	.pr_attach	= can_attach,
    679  1.1.2.1  bouyer 	.pr_detach	= can_detach,
    680  1.1.2.1  bouyer 	.pr_accept	= can_accept,
    681  1.1.2.1  bouyer 	.pr_bind	= can_bind,
    682  1.1.2.1  bouyer 	.pr_listen	= can_listen,
    683  1.1.2.1  bouyer 	.pr_connect	= can_connect,
    684  1.1.2.1  bouyer 	.pr_connect2	= can_connect2,
    685  1.1.2.1  bouyer 	.pr_disconnect	= can_disconnect,
    686  1.1.2.1  bouyer 	.pr_shutdown	= can_shutdown,
    687  1.1.2.1  bouyer 	.pr_abort	= can_abort,
    688  1.1.2.1  bouyer 	.pr_ioctl	= can_ioctl,
    689  1.1.2.1  bouyer 	.pr_stat	= can_stat,
    690  1.1.2.1  bouyer 	.pr_peeraddr	= can_peeraddr,
    691  1.1.2.1  bouyer 	.pr_sockaddr	= can_sockaddr,
    692  1.1.2.1  bouyer 	.pr_rcvd	= can_rcvd,
    693  1.1.2.1  bouyer 	.pr_recvoob	= can_recvoob,
    694  1.1.2.1  bouyer 	.pr_send	= can_send,
    695  1.1.2.1  bouyer 	.pr_sendoob	= can_sendoob,
    696  1.1.2.1  bouyer 	.pr_purgeif	= can_purgeif,
    697  1.1.2.1  bouyer };
    698