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