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