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