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