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