xref: /netbsd-src/sys/netcan/can.c (revision a0698ed9d41653d7a2378819ad501a285ca0d401)
1 /*	$NetBSD: can.c,v 1.6 2018/11/15 10:23:56 maxv 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.6 2018/11/15 10:23:56 maxv 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 		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 		ifp->if_ipackets++;
305 		ifp->if_ibytes += m->m_pkthdr.len;
306 		schednetisr(NETISR_CAN);
307 	}
308 }
309 
310 void
311 canintr(void)
312 {
313 	int		rcv_ifindex;
314 	struct mbuf    *m;
315 
316 	struct sockaddr_can from;
317 	struct canpcb   *canp;
318 	struct m_tag	*sotag;
319 	struct canpcb	*sender_canp;
320 
321 	mutex_enter(softnet_lock);
322 	for (;;) {
323 		IFQ_LOCK(&canintrq);
324 		IF_DEQUEUE(&canintrq, m);
325 		IFQ_UNLOCK(&canintrq);
326 
327 		if (m == NULL)	/* no more queued packets */
328 			break;
329 
330 #if 0
331 		m_claim(m, &can_rx_mowner);
332 #endif
333 		sotag = m_tag_find(m, PACKET_TAG_SO);
334 		if (sotag) {
335 			sender_canp = *(struct canpcb **)(sotag + 1);
336 			m_tag_delete(m, sotag);
337 			KASSERT(sender_canp != NULL);
338 			/* if the sender doesn't want loopback, don't do it */
339 			if ((sender_canp->canp_flags & CANP_NO_LOOPBACK) != 0) {
340 				m_freem(m);
341 				canp_unref(sender_canp);
342 				continue;
343 			}
344 		} else {
345 			sender_canp = NULL;
346 		}
347 		memset(&from, 0, sizeof(struct sockaddr_can));
348 		rcv_ifindex = m->m_pkthdr.rcvif_index;
349 		from.can_ifindex = rcv_ifindex;
350 		from.can_len = sizeof(struct sockaddr_can);
351 		from.can_family = AF_CAN;
352 
353 		TAILQ_FOREACH(canp, &cbtable.canpt_queue, canp_queue) {
354 			struct mbuf *mc;
355 
356 			mutex_enter(&canp->canp_mtx);
357 			/* skip if we're detached */
358 			if (canp->canp_state == CANP_DETACHED) {
359 				mutex_exit(&canp->canp_mtx);
360 				continue;
361 			}
362 
363 			/* don't loop back to sockets on other interfaces */
364 			if (canp->canp_ifp != NULL &&
365 			    canp->canp_ifp->if_index != rcv_ifindex) {
366 				mutex_exit(&canp->canp_mtx);
367 				continue;
368 			}
369 			/* don't loop back to myself if I don't want it */
370 			if (canp == sender_canp &&
371 			    (canp->canp_flags & CANP_RECEIVE_OWN) == 0) {
372 				mutex_exit(&canp->canp_mtx);
373 				continue;
374 			}
375 
376 			/* skip if the accept filter doen't match this pkt */
377 			if (!can_pcbfilter(canp, m)) {
378 				mutex_exit(&canp->canp_mtx);
379 				continue;
380 			}
381 
382 			if (TAILQ_NEXT(canp, canp_queue) != NULL) {
383 				/*
384 				 * we can't be sure we won't need
385 				 * the original mbuf later so copy
386 				 */
387 				mc = m_copypacket(m, M_NOWAIT);
388 				if (mc == NULL) {
389 					/* deliver this mbuf and abort */
390 					mc = m;
391 					m = NULL;
392 				}
393 			} else {
394 				mc = m;
395 				m = NULL;
396 			}
397 			if (sbappendaddr(&canp->canp_socket->so_rcv,
398 					 (struct sockaddr *) &from, mc,
399 					 (struct mbuf *) 0) == 0) {
400 				soroverflow(canp->canp_socket);
401 				m_freem(mc);
402 			} else
403 				sorwakeup(canp->canp_socket);
404 			mutex_exit(&canp->canp_mtx);
405 			if (m == NULL)
406 				break;
407 		}
408 		if (sender_canp) {
409 			canp_unref(sender_canp);
410 		}
411 		/* If it didn't go anywhere just delete it */
412 		if (m) {
413 			m_freem(m);
414 		}
415 	}
416 	mutex_exit(softnet_lock);
417 }
418 
419 void
420 can_bpf_mtap(struct ifnet *ifp, struct mbuf *m, bool do_softint)
421 {
422 	/* bpf wants the CAN id in network byte order */
423 	struct can_frame *cf;
424 	canid_t oid;
425 
426 	cf = mtod(m, struct can_frame *);
427 	oid = cf->can_id;
428 	cf->can_id = htonl(oid);
429 	/* Assume the direction is input when do_softint is set. */
430 	if (do_softint)
431 		bpf_mtap_softint(ifp, m);
432 	else
433 		bpf_mtap(ifp, m, BPF_D_OUT);
434 	cf->can_id = oid;
435 }
436 
437 static int
438 can_attach(struct socket *so, int proto)
439 {
440 	int error;
441 
442 	KASSERT(sotocanpcb(so) == NULL);
443 
444 	/* Assign the lock (must happen even if we will error out). */
445 	sosetlock(so);
446 
447 #ifdef MBUFTRACE
448 	so->so_mowner = &can_mowner;
449 	so->so_rcv.sb_mowner = &can_rx_mowner;
450 	so->so_snd.sb_mowner = &can_tx_mowner;
451 #endif
452 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
453 		error = soreserve(so, can_sendspace, can_recvspace);
454 		if (error) {
455 			return error;
456 		}
457 	}
458 
459 	error = can_pcballoc(so, &cbtable);
460 	if (error) {
461 		return error;
462 	}
463 	KASSERT(solocked(so));
464 
465 	return error;
466 }
467 
468 static void
469 can_detach(struct socket *so)
470 {
471 	struct canpcb *canp;
472 
473 	KASSERT(solocked(so));
474 	canp = sotocanpcb(so);
475 	can_pcbdetach(canp);
476 }
477 
478 static int
479 can_accept(struct socket *so, struct sockaddr *nam)
480 {
481 	KASSERT(solocked(so));
482 
483 	panic("can_accept");
484 
485 	return EOPNOTSUPP;
486 }
487 
488 static int
489 can_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
490 {
491 	struct canpcb *canp = sotocanpcb(so);
492 	struct sockaddr_can *scan = (struct sockaddr_can *)nam;
493 
494 	KASSERT(solocked(so));
495 	KASSERT(nam != NULL);
496 
497 	return can_pcbbind(canp, scan, l);
498 }
499 
500 static int
501 can_listen(struct socket *so, struct lwp *l)
502 {
503 	KASSERT(solocked(so));
504 
505 	return EOPNOTSUPP;
506 }
507 
508 static int
509 can_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
510 {
511 	struct canpcb *canp = sotocanpcb(so);
512 	int error = 0;
513 
514 	KASSERT(solocked(so));
515 	KASSERT(canp != NULL);
516 	KASSERT(nam != NULL);
517 
518 	error = can_pcbconnect(canp, (struct sockaddr_can *)nam);
519 	if (! error)
520 		soisconnected(so);
521 	return error;
522 }
523 
524 static int
525 can_connect2(struct socket *so, struct socket *so2)
526 {
527 	KASSERT(solocked(so));
528 
529 	return EOPNOTSUPP;
530 }
531 
532 static int
533 can_disconnect(struct socket *so)
534 {
535 	struct canpcb *canp = sotocanpcb(so);
536 
537 	KASSERT(solocked(so));
538 	KASSERT(canp != NULL);
539 
540 	/*soisdisconnected(so);*/
541 	so->so_state &= ~SS_ISCONNECTED;	/* XXX */
542 	can_pcbdisconnect(canp);
543 	return 0;
544 }
545 
546 static int
547 can_shutdown(struct socket *so)
548 {
549 	KASSERT(solocked(so));
550 
551 	socantsendmore(so);
552 	return 0;
553 }
554 
555 static int
556 can_abort(struct socket *so)
557 {
558 	KASSERT(solocked(so));
559 
560 	panic("can_abort");
561 
562 	return EOPNOTSUPP;
563 }
564 
565 static int
566 can_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
567 {
568 	return can_control(so, cmd, nam, ifp);
569 }
570 
571 static int
572 can_stat(struct socket *so, struct stat *ub)
573 {
574 	KASSERT(solocked(so));
575 
576 	/* stat: don't bother with a blocksize. */
577 	return 0;
578 }
579 
580 static int
581 can_peeraddr(struct socket *so, struct sockaddr *nam)
582 {
583 	KASSERT(solocked(so));
584 	KASSERT(sotocanpcb(so) != NULL);
585 	KASSERT(nam != NULL);
586 
587 	return EOPNOTSUPP;
588 }
589 
590 static int
591 can_sockaddr(struct socket *so, struct sockaddr *nam)
592 {
593 	KASSERT(solocked(so));
594 	KASSERT(sotocanpcb(so) != NULL);
595 	KASSERT(nam != NULL);
596 
597 	can_setsockaddr(sotocanpcb(so), (struct sockaddr_can *)nam);
598 
599 	return 0;
600 }
601 
602 static int
603 can_rcvd(struct socket *so, int flags, struct lwp *l)
604 {
605 	KASSERT(solocked(so));
606 
607 	return EOPNOTSUPP;
608 }
609 
610 static int
611 can_recvoob(struct socket *so, struct mbuf *m, int flags)
612 {
613 	KASSERT(solocked(so));
614 
615 	return EOPNOTSUPP;
616 }
617 
618 static int
619 can_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
620     struct mbuf *control, struct lwp *l)
621 {
622 	struct canpcb *canp = sotocanpcb(so);
623 	int error = 0;
624 	int s;
625 
626 	if (control && control->m_len) {
627 		m_freem(control);
628 		error = EINVAL;
629 		goto err;
630 	}
631 	if (m->m_len > sizeof(struct can_frame) ||
632 	   m->m_len < offsetof(struct can_frame, can_dlc)) {
633 		error = EINVAL;
634 		goto err;
635 	}
636 
637 	/* we expect all data in the first mbuf */
638 	KASSERT((m->m_flags & M_PKTHDR) != 0);
639 	KASSERT(m->m_len == m->m_pkthdr.len);
640 
641 	if (nam) {
642 		if ((so->so_state & SS_ISCONNECTED) != 0) {
643 			error = EISCONN;
644 			goto err;
645 		}
646 		s = splnet();
647 		error = can_pcbbind(canp, (struct sockaddr_can *)nam, l);
648 		if (error) {
649 			splx(s);
650 			goto err;
651 		}
652 	} else {
653 		if ((so->so_state & SS_ISCONNECTED) == 0) {
654 			error =  EDESTADDRREQ;
655 			goto err;
656 		}
657 	}
658 	error = can_output(m, canp);
659 	if (nam) {
660 		struct sockaddr_can lscan;
661 		memset(&lscan, 0, sizeof(lscan));
662 		lscan.can_family = AF_CAN;
663 		lscan.can_len = sizeof(lscan);
664 		can_pcbbind(canp, &lscan, l);
665 	}
666 	if (error)
667 		goto err;
668 	return 0;
669 
670 err:
671 	m_freem(m);
672 	return error;
673 }
674 
675 static int
676 can_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
677 {
678 	KASSERT(solocked(so));
679 
680 	m_freem(m);
681 	m_freem(control);
682 
683 	return EOPNOTSUPP;
684 }
685 
686 #if 0
687 int
688 can_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
689 	   struct mbuf *control, struct lwp *l)
690 {
691 	struct canpcb *canp;
692 	int s;
693 	int error = 0;
694 
695 	if (req == PRU_CONTROL)
696 		 return (can_control(so, (long)m, nam,
697 		     (struct ifnet *)control));
698 
699 	if (req == PRU_PURGEIF) {
700 #if 0
701 		can_pcbpurgeif0(&udbtable, (struct ifnet *)control);
702 		can_purgeif((struct ifnet *)control);
703 		can_pcbpurgeif(&udbtable, (struct ifnet *)control);
704 #endif
705 		return (0);
706 	}
707 
708 	s = splsoftnet();
709 	canp = sotocanpcb(so);
710 #ifdef DIAGNOSTIC
711 	if (req != PRU_SEND && req != PRU_SENDOOB && control)
712 		panic("can_usrreq: unexpected control mbuf");
713 #endif
714 	if (canp == 0 && req != PRU_ATTACH) {
715 		printf("can_usrreq: no pcb %p %d\n", canp, req);
716 		error = EINVAL;
717 		goto release;
718 	}
719 
720 	/*
721 	 * Note: need to block can_input while changing
722 	 * the can pcb queue and/or pcb addresses.
723 	 */
724 	switch (req) {
725 
726 	  case PRU_ATTACH:
727 	      if (canp != 0) {
728 			 error = EISCONN;
729 			 break;
730 		 }
731 #ifdef MBUFTRACE
732 		so->so_mowner = &can_mowner;
733 		so->so_rcv.sb_mowner = &can_rx_mowner;
734 		so->so_snd.sb_mowner = &can_tx_mowner;
735 #endif
736 		if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
737 			error = soreserve(so, can_sendspace, can_recvspace);
738 			if (error)
739 				break;
740 		}
741 		error = can_pcballoc(so, &cbtable);
742 		if (error)
743 			break;
744 		canp = sotocanpcb(so);
745 #if 0
746 		inp->inp_ip.ip_ttl = ip_defttl;
747 #endif
748 		break;
749 
750 	case PRU_DETACH:
751 		can_pcbdetach(canp);
752 		break;
753 
754 	case PRU_BIND:
755 		error = can_pcbbind(canp, nam, l);
756 		break;
757 
758 	case PRU_LISTEN:
759 		error = EOPNOTSUPP;
760 		break;
761 
762 	case PRU_CONNECT:
763 		error = can_pcbconnect(canp, nam);
764 		if (error)
765 			break;
766 		soisconnected(so);
767 		break;
768 
769 	case PRU_CONNECT2:
770 		error = EOPNOTSUPP;
771 		break;
772 
773 	case PRU_DISCONNECT:
774 		/*soisdisconnected(so);*/
775 		so->so_state &= ~SS_ISCONNECTED;	/* XXX */
776 		can_pcbdisconnect(canp);
777 		can_pcbstate(canp, CANP_BOUND);		/* XXX */
778 		break;
779 
780 	case PRU_SHUTDOWN:
781 		socantsendmore(so);
782 		break;
783 
784 	case PRU_RCVD:
785 		error = EOPNOTSUPP;
786 		break;
787 
788 	case PRU_SEND:
789 		break;
790 
791 	case PRU_SENSE:
792 		/*
793 		 * stat: don't bother with a blocksize.
794 		 */
795 		splx(s);
796 		return (0);
797 
798 	case PRU_RCVOOB:
799 		error =  EOPNOTSUPP;
800 		break;
801 
802 	case PRU_SENDOOB:
803 		m_freem(control);
804 		m_freem(m);
805 		error =  EOPNOTSUPP;
806 		break;
807 
808 	case PRU_SOCKADDR:
809 
810 		break;
811 
812 	case PRU_PEERADDR:
813 		error =  EOPNOTSUPP;
814 		break;
815 
816 	default:
817 		panic("can_usrreq");
818 	}
819 
820 release:
821 	splx(s);
822 	return (error);
823 }
824 #endif
825 
826 #if 0
827 static void
828 can_notify(struct canpcb *canp, int errno)
829 {
830 
831 	canp->canp_socket->so_error = errno;
832 	sorwakeup(canp->canp_socket);
833 	sowwakeup(canp->canp_socket);
834 }
835 
836 void *
837 can_ctlinput(int cmd, struct sockaddr *sa, void *v)
838 {
839 	struct ip *ip = v;
840 	struct canhdr *uh;
841 	void (*notify) __P((struct inpcb *, int)) = can_notify;
842 	int errno;
843 
844 	if (sa->sa_family != AF_CAN
845 	 || sa->sa_len != sizeof(struct sockaddr_can))
846 		return NULL;
847 	if ((unsigned)cmd >= PRC_NCMDS)
848 		return NULL;
849 	errno = inetctlerrmap[cmd];
850 	if (PRC_IS_REDIRECT(cmd))
851 		notify = in_rtchange, ip = 0;
852 	else if (cmd == PRC_HOSTDEAD)
853 		ip = 0;
854 	else if (errno == 0)
855 		return NULL;
856 	if (ip) {
857 		uh = (struct canhdr *)((caddr_t)ip + (ip->ip_hl << 2));
858 		in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport,
859 		    ip->ip_src, uh->uh_sport, errno, notify);
860 
861 		/* XXX mapped address case */
862 	} else
863 		can_pcbnotifyall(&cbtable, satoscan(sa)->scan_addr, errno,
864 		    notify);
865 	return NULL;
866 }
867 #endif
868 
869 static int
870 can_raw_getop(struct canpcb *canp, struct sockopt *sopt)
871 {
872 	int optval = 0;
873 	int error;
874 
875 	switch (sopt->sopt_name) {
876 	case CAN_RAW_LOOPBACK:
877 		optval = (canp->canp_flags & CANP_NO_LOOPBACK) ? 0 : 1;
878 		error = sockopt_set(sopt, &optval, sizeof(optval));
879 		break;
880 	case CAN_RAW_RECV_OWN_MSGS:
881 		optval = (canp->canp_flags & CANP_RECEIVE_OWN) ? 1 : 0;
882 		error = sockopt_set(sopt, &optval, sizeof(optval));
883 		break;
884 	case CAN_RAW_FILTER:
885 		error = sockopt_set(sopt, canp->canp_filters,
886 		    sizeof(struct can_filter) * canp->canp_nfilters);
887 		break;
888 	default:
889 		error = ENOPROTOOPT;
890 		break;
891 	}
892 	return error;
893 }
894 
895 static int
896 can_raw_setop(struct canpcb *canp, struct sockopt *sopt)
897 {
898 	int optval = 0;
899 	int error;
900 
901 	switch (sopt->sopt_name) {
902 	case CAN_RAW_LOOPBACK:
903 		error = sockopt_getint(sopt, &optval);
904 		if (error == 0) {
905 			if (optval) {
906 				canp->canp_flags &= ~CANP_NO_LOOPBACK;
907 			} else {
908 				canp->canp_flags |= CANP_NO_LOOPBACK;
909 			}
910 		}
911 		break;
912 	case CAN_RAW_RECV_OWN_MSGS:
913 		error = sockopt_getint(sopt, &optval);
914 		if (error == 0) {
915 			if (optval) {
916 				canp->canp_flags |= CANP_RECEIVE_OWN;
917 			} else {
918 				canp->canp_flags &= ~CANP_RECEIVE_OWN;
919 			}
920 		}
921 		break;
922 	case CAN_RAW_FILTER:
923 		{
924 		int nfilters = sopt->sopt_size / sizeof(struct can_filter);
925 		if (sopt->sopt_size % sizeof(struct can_filter) != 0)
926 			return EINVAL;
927 		mutex_enter(&canp->canp_mtx);
928 		error = can_pcbsetfilter(canp, sopt->sopt_data, nfilters);
929 		mutex_exit(&canp->canp_mtx);
930 		break;
931 		}
932 	default:
933 		error = ENOPROTOOPT;
934 		break;
935 	}
936 	return error;
937 }
938 
939 /*
940  * Called by getsockopt and setsockopt.
941  *
942  */
943 int
944 can_ctloutput(int op, struct socket *so, struct sockopt *sopt)
945 {
946 	struct canpcb *canp;
947 	int error;
948 	int s;
949 
950 	if (so->so_proto->pr_domain->dom_family != PF_CAN)
951 		return EAFNOSUPPORT;
952 
953 	if (sopt->sopt_level != SOL_CAN_RAW)
954 		return EINVAL;
955 
956 	s = splsoftnet();
957 	canp = sotocanpcb(so);
958 	if (canp == NULL) {
959 		splx(s);
960 		return ECONNRESET;
961 	}
962 
963 	if (op == PRCO_SETOPT) {
964 		error = can_raw_setop(canp, sopt);
965 	} else if (op ==  PRCO_GETOPT) {
966 		error = can_raw_getop(canp, sopt);
967 	} else {
968 		error = EINVAL;
969 	}
970 	splx(s);
971 	return error;
972 }
973 
974 PR_WRAP_USRREQS(can)
975 #define	can_attach	can_attach_wrapper
976 #define	can_detach	can_detach_wrapper
977 #define	can_accept	can_accept_wrapper
978 #define	can_bind	can_bind_wrapper
979 #define	can_listen	can_listen_wrapper
980 #define	can_connect	can_connect_wrapper
981 #define	can_connect2	can_connect2_wrapper
982 #define	can_disconnect	can_disconnect_wrapper
983 #define	can_shutdown	can_shutdown_wrapper
984 #define	can_abort	can_abort_wrapper
985 #define	can_ioctl	can_ioctl_wrapper
986 #define	can_stat	can_stat_wrapper
987 #define	can_peeraddr	can_peeraddr_wrapper
988 #define	can_sockaddr	can_sockaddr_wrapper
989 #define	can_rcvd	can_rcvd_wrapper
990 #define	can_recvoob	can_recvoob_wrapper
991 #define	can_send	can_send_wrapper
992 #define	can_sendoob	can_sendoob_wrapper
993 #define	can_purgeif	can_purgeif_wrapper
994 
995 const struct pr_usrreqs can_usrreqs = {
996 	.pr_attach	= can_attach,
997 	.pr_detach	= can_detach,
998 	.pr_accept	= can_accept,
999 	.pr_bind	= can_bind,
1000 	.pr_listen	= can_listen,
1001 	.pr_connect	= can_connect,
1002 	.pr_connect2	= can_connect2,
1003 	.pr_disconnect	= can_disconnect,
1004 	.pr_shutdown	= can_shutdown,
1005 	.pr_abort	= can_abort,
1006 	.pr_ioctl	= can_ioctl,
1007 	.pr_stat	= can_stat,
1008 	.pr_peeraddr	= can_peeraddr,
1009 	.pr_sockaddr	= can_sockaddr,
1010 	.pr_rcvd	= can_rcvd,
1011 	.pr_recvoob	= can_recvoob,
1012 	.pr_send	= can_send,
1013 	.pr_sendoob	= can_sendoob,
1014 	.pr_purgeif	= can_purgeif,
1015 };
1016