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