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