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