1 | /* $NetBSD: ddp_usrreq.c,v 1.69 2016/10/03 11:06:06 ozaki-r Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1990,1991 Regents of The University of Michigan. |
5 | * All Rights Reserved. |
6 | * |
7 | * Permission to use, copy, modify, and distribute this software and |
8 | * its documentation for any purpose and without fee is hereby granted, |
9 | * provided that the above copyright notice appears in all copies and |
10 | * that both that copyright notice and this permission notice appear |
11 | * in supporting documentation, and that the name of The University |
12 | * of Michigan not be used in advertising or publicity pertaining to |
13 | * distribution of the software without specific, written prior |
14 | * permission. This software is supplied as is without expressed or |
15 | * implied warranties of any kind. |
16 | * |
17 | * This product includes software developed by the University of |
18 | * California, Berkeley and its contributors. |
19 | * |
20 | * Research Systems Unix Group |
21 | * The University of Michigan |
22 | * c/o Wesley Craig |
23 | * 535 W. William Street |
24 | * Ann Arbor, Michigan |
25 | * +1-313-764-2278 |
26 | * netatalk@umich.edu |
27 | */ |
28 | |
29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: ddp_usrreq.c,v 1.69 2016/10/03 11:06:06 ozaki-r Exp $" ); |
31 | |
32 | #include "opt_mbuftrace.h" |
33 | |
34 | #include <sys/param.h> |
35 | #include <sys/errno.h> |
36 | #include <sys/systm.h> |
37 | #include <sys/mbuf.h> |
38 | #include <sys/ioctl.h> |
39 | #include <sys/queue.h> |
40 | #include <sys/socket.h> |
41 | #include <sys/socketvar.h> |
42 | #include <sys/protosw.h> |
43 | #include <sys/kauth.h> |
44 | #include <sys/kmem.h> |
45 | #include <sys/sysctl.h> |
46 | #include <net/if.h> |
47 | #include <net/route.h> |
48 | #include <net/if_ether.h> |
49 | #include <net/net_stats.h> |
50 | #include <netinet/in.h> |
51 | |
52 | #include <netatalk/at.h> |
53 | #include <netatalk/at_var.h> |
54 | #include <netatalk/ddp_var.h> |
55 | #include <netatalk/ddp_private.h> |
56 | #include <netatalk/aarp.h> |
57 | #include <netatalk/at_extern.h> |
58 | |
59 | static void at_pcbdisconnect(struct ddpcb *); |
60 | static void at_sockaddr(struct ddpcb *, struct sockaddr_at *); |
61 | static int at_pcbsetaddr(struct ddpcb *, struct sockaddr_at *); |
62 | static int at_pcbconnect(struct ddpcb *, struct sockaddr_at *); |
63 | static void ddp_detach(struct socket *); |
64 | |
65 | struct ifqueue atintrq1, atintrq2; |
66 | struct ddpcb *ddp_ports[ATPORT_LAST]; |
67 | struct ddpcb *ddpcb = NULL; |
68 | percpu_t *ddpstat_percpu; |
69 | struct at_ifaddrhead at_ifaddr; /* Here as inited in this file */ |
70 | u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */ |
71 | u_long ddp_recvspace = 25 * (587 + sizeof(struct sockaddr_at)); |
72 | |
73 | #ifdef MBUFTRACE |
74 | struct mowner atalk_rx_mowner = MOWNER_INIT("atalk" , "rx" ); |
75 | struct mowner atalk_tx_mowner = MOWNER_INIT("atalk" , "tx" ); |
76 | #endif |
77 | |
78 | static void |
79 | at_sockaddr(struct ddpcb *ddp, struct sockaddr_at *addr) |
80 | { |
81 | |
82 | *addr = ddp->ddp_lsat; |
83 | } |
84 | |
85 | static int |
86 | at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr_at *sat) |
87 | { |
88 | struct sockaddr_at lsat; |
89 | struct at_ifaddr *aa; |
90 | struct ddpcb *ddpp; |
91 | |
92 | if (ddp->ddp_lsat.sat_port != ATADDR_ANYPORT) { /* shouldn't be bound */ |
93 | return (EINVAL); |
94 | } |
95 | if (NULL != sat) { /* validate passed address */ |
96 | |
97 | if (sat->sat_family != AF_APPLETALK) |
98 | return (EAFNOSUPPORT); |
99 | |
100 | if (sat->sat_addr.s_node != ATADDR_ANYNODE || |
101 | sat->sat_addr.s_net != ATADDR_ANYNET) { |
102 | TAILQ_FOREACH(aa, &at_ifaddr, aa_list) { |
103 | if ((sat->sat_addr.s_net == |
104 | AA_SAT(aa)->sat_addr.s_net) && |
105 | (sat->sat_addr.s_node == |
106 | AA_SAT(aa)->sat_addr.s_node)) |
107 | break; |
108 | } |
109 | if (!aa) |
110 | return (EADDRNOTAVAIL); |
111 | } |
112 | if (sat->sat_port != ATADDR_ANYPORT) { |
113 | int error; |
114 | |
115 | if (sat->sat_port < ATPORT_FIRST || |
116 | sat->sat_port >= ATPORT_LAST) |
117 | return (EINVAL); |
118 | |
119 | if (sat->sat_port < ATPORT_RESERVED && |
120 | (error = kauth_authorize_network(curlwp->l_cred, |
121 | KAUTH_NETWORK_BIND, KAUTH_REQ_NETWORK_BIND_PRIVPORT, |
122 | ddpcb->ddp_socket, sat, NULL)) != 0) |
123 | return (error); |
124 | } |
125 | } else { |
126 | memset((void *) & lsat, 0, sizeof(struct sockaddr_at)); |
127 | lsat.sat_len = sizeof(struct sockaddr_at); |
128 | lsat.sat_addr.s_node = ATADDR_ANYNODE; |
129 | lsat.sat_addr.s_net = ATADDR_ANYNET; |
130 | lsat.sat_family = AF_APPLETALK; |
131 | sat = &lsat; |
132 | } |
133 | |
134 | if (sat->sat_addr.s_node == ATADDR_ANYNODE && |
135 | sat->sat_addr.s_net == ATADDR_ANYNET) { |
136 | if (TAILQ_EMPTY(&at_ifaddr)) |
137 | return EADDRNOTAVAIL; |
138 | sat->sat_addr = AA_SAT(TAILQ_FIRST(&at_ifaddr))->sat_addr; |
139 | } |
140 | ddp->ddp_lsat = *sat; |
141 | |
142 | /* |
143 | * Choose port. |
144 | */ |
145 | if (sat->sat_port == ATADDR_ANYPORT) { |
146 | for (sat->sat_port = ATPORT_RESERVED; |
147 | sat->sat_port < ATPORT_LAST; sat->sat_port++) { |
148 | if (ddp_ports[sat->sat_port - 1] == 0) |
149 | break; |
150 | } |
151 | if (sat->sat_port == ATPORT_LAST) { |
152 | return (EADDRNOTAVAIL); |
153 | } |
154 | ddp->ddp_lsat.sat_port = sat->sat_port; |
155 | ddp_ports[sat->sat_port - 1] = ddp; |
156 | } else { |
157 | for (ddpp = ddp_ports[sat->sat_port - 1]; ddpp; |
158 | ddpp = ddpp->ddp_pnext) { |
159 | if (ddpp->ddp_lsat.sat_addr.s_net == |
160 | sat->sat_addr.s_net && |
161 | ddpp->ddp_lsat.sat_addr.s_node == |
162 | sat->sat_addr.s_node) |
163 | break; |
164 | } |
165 | if (ddpp != NULL) |
166 | return (EADDRINUSE); |
167 | |
168 | ddp->ddp_pnext = ddp_ports[sat->sat_port - 1]; |
169 | ddp_ports[sat->sat_port - 1] = ddp; |
170 | if (ddp->ddp_pnext) |
171 | ddp->ddp_pnext->ddp_pprev = ddp; |
172 | } |
173 | |
174 | return 0; |
175 | } |
176 | |
177 | static int |
178 | at_pcbconnect(struct ddpcb *ddp, struct sockaddr_at *sat) |
179 | { |
180 | struct rtentry *rt; |
181 | const struct sockaddr_at *cdst; |
182 | struct route *ro; |
183 | struct at_ifaddr *aa; |
184 | struct ifnet *ifp; |
185 | u_short hintnet = 0, net; |
186 | |
187 | if (sat->sat_family != AF_APPLETALK) { |
188 | return EAFNOSUPPORT; |
189 | } |
190 | /* |
191 | * Under phase 2, network 0 means "the network". We take "the |
192 | * network" to mean the network the control block is bound to. |
193 | * If the control block is not bound, there is an error. |
194 | */ |
195 | if (sat->sat_addr.s_net == ATADDR_ANYNET |
196 | && sat->sat_addr.s_node != ATADDR_ANYNODE) { |
197 | if (ddp->ddp_lsat.sat_port == ATADDR_ANYPORT) { |
198 | return EADDRNOTAVAIL; |
199 | } |
200 | hintnet = ddp->ddp_lsat.sat_addr.s_net; |
201 | } |
202 | ro = &ddp->ddp_route; |
203 | /* |
204 | * If we've got an old route for this pcb, check that it is valid. |
205 | * If we've changed our address, we may have an old "good looking" |
206 | * route here. Attempt to detect it. |
207 | */ |
208 | if ((rt = rtcache_validate(ro)) != NULL || |
209 | (rt = rtcache_update(ro, 1)) != NULL) { |
210 | if (hintnet) { |
211 | net = hintnet; |
212 | } else { |
213 | net = sat->sat_addr.s_net; |
214 | } |
215 | if ((ifp = rt->rt_ifp) != NULL) { |
216 | TAILQ_FOREACH(aa, &at_ifaddr, aa_list) { |
217 | if (aa->aa_ifp == ifp && |
218 | ntohs(net) >= ntohs(aa->aa_firstnet) && |
219 | ntohs(net) <= ntohs(aa->aa_lastnet)) { |
220 | break; |
221 | } |
222 | } |
223 | } else |
224 | aa = NULL; |
225 | cdst = satocsat(rtcache_getdst(ro)); |
226 | if (aa == NULL || (cdst->sat_addr.s_net != |
227 | (hintnet ? hintnet : sat->sat_addr.s_net) || |
228 | cdst->sat_addr.s_node != sat->sat_addr.s_node)) { |
229 | rtcache_free(ro); |
230 | rt = NULL; |
231 | } |
232 | } |
233 | /* |
234 | * If we've got no route for this interface, try to find one. |
235 | */ |
236 | if (rt == NULL) { |
237 | union { |
238 | struct sockaddr dst; |
239 | struct sockaddr_at dsta; |
240 | } u; |
241 | |
242 | sockaddr_at_init(&u.dsta, &sat->sat_addr, 0); |
243 | if (hintnet) |
244 | u.dsta.sat_addr.s_net = hintnet; |
245 | rt = rtcache_lookup(ro, &u.dst); |
246 | } |
247 | /* |
248 | * Make sure any route that we have has a valid interface. |
249 | */ |
250 | if (rt != NULL && (ifp = rt->rt_ifp) != NULL) { |
251 | TAILQ_FOREACH(aa, &at_ifaddr, aa_list) { |
252 | if (aa->aa_ifp == ifp) |
253 | break; |
254 | } |
255 | } else |
256 | aa = NULL; |
257 | if (aa == NULL) |
258 | return ENETUNREACH; |
259 | ddp->ddp_fsat = *sat; |
260 | if (ddp->ddp_lsat.sat_port == ATADDR_ANYPORT) |
261 | return at_pcbsetaddr(ddp, NULL); |
262 | return 0; |
263 | } |
264 | |
265 | static void |
266 | at_pcbdisconnect(struct ddpcb *ddp) |
267 | { |
268 | ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET; |
269 | ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE; |
270 | ddp->ddp_fsat.sat_port = ATADDR_ANYPORT; |
271 | } |
272 | |
273 | static int |
274 | ddp_attach(struct socket *so, int proto) |
275 | { |
276 | struct ddpcb *ddp; |
277 | int error; |
278 | |
279 | KASSERT(sotoddpcb(so) == NULL); |
280 | sosetlock(so); |
281 | #ifdef MBUFTRACE |
282 | so->so_rcv.sb_mowner = &atalk_rx_mowner; |
283 | so->so_snd.sb_mowner = &atalk_tx_mowner; |
284 | #endif |
285 | error = soreserve(so, ddp_sendspace, ddp_recvspace); |
286 | if (error) { |
287 | return error; |
288 | } |
289 | |
290 | ddp = kmem_zalloc(sizeof(*ddp), KM_SLEEP); |
291 | ddp->ddp_lsat.sat_port = ATADDR_ANYPORT; |
292 | |
293 | ddp->ddp_next = ddpcb; |
294 | ddp->ddp_prev = NULL; |
295 | ddp->ddp_pprev = NULL; |
296 | ddp->ddp_pnext = NULL; |
297 | if (ddpcb) { |
298 | ddpcb->ddp_prev = ddp; |
299 | } |
300 | ddpcb = ddp; |
301 | |
302 | ddp->ddp_socket = so; |
303 | so->so_pcb = ddp; |
304 | return 0; |
305 | } |
306 | |
307 | static void |
308 | ddp_detach(struct socket *so) |
309 | { |
310 | struct ddpcb *ddp = sotoddpcb(so); |
311 | |
312 | soisdisconnected(so); |
313 | so->so_pcb = NULL; |
314 | /* sofree drops the lock */ |
315 | sofree(so); |
316 | mutex_enter(softnet_lock); |
317 | |
318 | /* remove ddp from ddp_ports list */ |
319 | if (ddp->ddp_lsat.sat_port != ATADDR_ANYPORT && |
320 | ddp_ports[ddp->ddp_lsat.sat_port - 1] != NULL) { |
321 | if (ddp->ddp_pprev != NULL) { |
322 | ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext; |
323 | } else { |
324 | ddp_ports[ddp->ddp_lsat.sat_port - 1] = ddp->ddp_pnext; |
325 | } |
326 | if (ddp->ddp_pnext != NULL) { |
327 | ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev; |
328 | } |
329 | } |
330 | rtcache_free(&ddp->ddp_route); |
331 | if (ddp->ddp_prev) { |
332 | ddp->ddp_prev->ddp_next = ddp->ddp_next; |
333 | } else { |
334 | ddpcb = ddp->ddp_next; |
335 | } |
336 | if (ddp->ddp_next) { |
337 | ddp->ddp_next->ddp_prev = ddp->ddp_prev; |
338 | } |
339 | kmem_free(ddp, sizeof(*ddp)); |
340 | } |
341 | |
342 | static int |
343 | ddp_accept(struct socket *so, struct sockaddr *nam) |
344 | { |
345 | KASSERT(solocked(so)); |
346 | |
347 | return EOPNOTSUPP; |
348 | } |
349 | |
350 | static int |
351 | ddp_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) |
352 | { |
353 | KASSERT(solocked(so)); |
354 | KASSERT(sotoddpcb(so) != NULL); |
355 | |
356 | return at_pcbsetaddr(sotoddpcb(so), (struct sockaddr_at *)nam); |
357 | } |
358 | |
359 | static int |
360 | ddp_listen(struct socket *so, struct lwp *l) |
361 | { |
362 | KASSERT(solocked(so)); |
363 | |
364 | return EOPNOTSUPP; |
365 | } |
366 | |
367 | static int |
368 | ddp_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) |
369 | { |
370 | struct ddpcb *ddp = sotoddpcb(so); |
371 | int error = 0; |
372 | |
373 | KASSERT(solocked(so)); |
374 | KASSERT(ddp != NULL); |
375 | KASSERT(nam != NULL); |
376 | |
377 | if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) |
378 | return EISCONN; |
379 | error = at_pcbconnect(ddp, (struct sockaddr_at *)nam); |
380 | if (error == 0) |
381 | soisconnected(so); |
382 | |
383 | return error; |
384 | } |
385 | |
386 | static int |
387 | ddp_connect2(struct socket *so, struct socket *so2) |
388 | { |
389 | KASSERT(solocked(so)); |
390 | |
391 | return EOPNOTSUPP; |
392 | } |
393 | |
394 | static int |
395 | ddp_disconnect(struct socket *so) |
396 | { |
397 | struct ddpcb *ddp = sotoddpcb(so); |
398 | |
399 | KASSERT(solocked(so)); |
400 | KASSERT(ddp != NULL); |
401 | |
402 | if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) |
403 | return ENOTCONN; |
404 | |
405 | at_pcbdisconnect(ddp); |
406 | soisdisconnected(so); |
407 | return 0; |
408 | } |
409 | |
410 | static int |
411 | ddp_shutdown(struct socket *so) |
412 | { |
413 | KASSERT(solocked(so)); |
414 | |
415 | socantsendmore(so); |
416 | return 0; |
417 | } |
418 | |
419 | static int |
420 | ddp_abort(struct socket *so) |
421 | { |
422 | KASSERT(solocked(so)); |
423 | |
424 | soisdisconnected(so); |
425 | ddp_detach(so); |
426 | return 0; |
427 | } |
428 | |
429 | static int |
430 | ddp_ioctl(struct socket *so, u_long cmd, void *addr, struct ifnet *ifp) |
431 | { |
432 | return at_control(cmd, addr, ifp); |
433 | } |
434 | |
435 | static int |
436 | ddp_stat(struct socket *so, struct stat *ub) |
437 | { |
438 | KASSERT(solocked(so)); |
439 | |
440 | /* stat: don't bother with a blocksize. */ |
441 | return 0; |
442 | } |
443 | |
444 | static int |
445 | ddp_peeraddr(struct socket *so, struct sockaddr *nam) |
446 | { |
447 | KASSERT(solocked(so)); |
448 | |
449 | return EOPNOTSUPP; |
450 | } |
451 | |
452 | static int |
453 | ddp_sockaddr(struct socket *so, struct sockaddr *nam) |
454 | { |
455 | KASSERT(solocked(so)); |
456 | KASSERT(sotoddpcb(so) != NULL); |
457 | KASSERT(nam != NULL); |
458 | |
459 | at_sockaddr(sotoddpcb(so), (struct sockaddr_at *)nam); |
460 | return 0; |
461 | } |
462 | |
463 | static int |
464 | ddp_rcvd(struct socket *so, int flags, struct lwp *l) |
465 | { |
466 | KASSERT(solocked(so)); |
467 | |
468 | return EOPNOTSUPP; |
469 | } |
470 | |
471 | static int |
472 | ddp_recvoob(struct socket *so, struct mbuf *m, int flags) |
473 | { |
474 | KASSERT(solocked(so)); |
475 | |
476 | return EOPNOTSUPP; |
477 | } |
478 | |
479 | static int |
480 | ddp_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, |
481 | struct mbuf *control, struct lwp *l) |
482 | { |
483 | struct ddpcb *ddp = sotoddpcb(so); |
484 | int error = 0; |
485 | int s = 0; /* XXX gcc 4.8 warns on sgimips */ |
486 | |
487 | KASSERT(solocked(so)); |
488 | KASSERT(ddp != NULL); |
489 | |
490 | if (nam) { |
491 | if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) |
492 | return EISCONN; |
493 | s = splnet(); |
494 | error = at_pcbconnect(ddp, (struct sockaddr_at *)nam); |
495 | if (error) { |
496 | splx(s); |
497 | return error; |
498 | } |
499 | } else { |
500 | if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) |
501 | return ENOTCONN; |
502 | } |
503 | |
504 | error = ddp_output(m, ddp); |
505 | m = NULL; |
506 | if (nam) { |
507 | at_pcbdisconnect(ddp); |
508 | splx(s); |
509 | } |
510 | |
511 | return error; |
512 | } |
513 | |
514 | static int |
515 | ddp_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) |
516 | { |
517 | KASSERT(solocked(so)); |
518 | |
519 | if (m) |
520 | m_freem(m); |
521 | |
522 | return EOPNOTSUPP; |
523 | } |
524 | |
525 | static int |
526 | ddp_purgeif(struct socket *so, struct ifnet *ifp) |
527 | { |
528 | |
529 | mutex_enter(softnet_lock); |
530 | at_purgeif(ifp); |
531 | mutex_exit(softnet_lock); |
532 | |
533 | return 0; |
534 | } |
535 | |
536 | /* |
537 | * For the moment, this just find the pcb with the correct local address. |
538 | * In the future, this will actually do some real searching, so we can use |
539 | * the sender's address to do de-multiplexing on a single port to many |
540 | * sockets (pcbs). |
541 | */ |
542 | struct ddpcb * |
543 | ddp_search( |
544 | struct sockaddr_at *from, |
545 | struct sockaddr_at *to, |
546 | struct at_ifaddr *aa) |
547 | { |
548 | struct ddpcb *ddp; |
549 | |
550 | /* |
551 | * Check for bad ports. |
552 | */ |
553 | if (to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST) |
554 | return NULL; |
555 | |
556 | /* |
557 | * Make sure the local address matches the sent address. What about |
558 | * the interface? |
559 | */ |
560 | for (ddp = ddp_ports[to->sat_port - 1]; ddp; ddp = ddp->ddp_pnext) { |
561 | /* XXX should we handle 0.YY? */ |
562 | |
563 | /* XXXX.YY to socket on destination interface */ |
564 | if (to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net && |
565 | to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node) { |
566 | break; |
567 | } |
568 | /* 0.255 to socket on receiving interface */ |
569 | if (to->sat_addr.s_node == ATADDR_BCAST && |
570 | (to->sat_addr.s_net == 0 || |
571 | to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net) && |
572 | ddp->ddp_lsat.sat_addr.s_net == AA_SAT(aa)->sat_addr.s_net) { |
573 | break; |
574 | } |
575 | /* XXXX.0 to socket on destination interface */ |
576 | if (to->sat_addr.s_net == aa->aa_firstnet && |
577 | to->sat_addr.s_node == 0 && |
578 | ntohs(ddp->ddp_lsat.sat_addr.s_net) >= |
579 | ntohs(aa->aa_firstnet) && |
580 | ntohs(ddp->ddp_lsat.sat_addr.s_net) <= |
581 | ntohs(aa->aa_lastnet)) { |
582 | break; |
583 | } |
584 | } |
585 | return (ddp); |
586 | } |
587 | |
588 | /* |
589 | * Initialize all the ddp & appletalk stuff |
590 | */ |
591 | void |
592 | ddp_init(void) |
593 | { |
594 | |
595 | ddpstat_percpu = percpu_alloc(sizeof(uint64_t) * DDP_NSTATS); |
596 | |
597 | TAILQ_INIT(&at_ifaddr); |
598 | atintrq1.ifq_maxlen = IFQ_MAXLEN; |
599 | atintrq2.ifq_maxlen = IFQ_MAXLEN; |
600 | IFQ_LOCK_INIT(&atintrq1); |
601 | IFQ_LOCK_INIT(&atintrq2); |
602 | |
603 | MOWNER_ATTACH(&atalk_tx_mowner); |
604 | MOWNER_ATTACH(&atalk_rx_mowner); |
605 | MOWNER_ATTACH(&aarp_mowner); |
606 | } |
607 | |
608 | PR_WRAP_USRREQS(ddp) |
609 | #define ddp_attach ddp_attach_wrapper |
610 | #define ddp_detach ddp_detach_wrapper |
611 | #define ddp_accept ddp_accept_wrapper |
612 | #define ddp_bind ddp_bind_wrapper |
613 | #define ddp_listen ddp_listen_wrapper |
614 | #define ddp_connect ddp_connect_wrapper |
615 | #define ddp_connect2 ddp_connect2_wrapper |
616 | #define ddp_disconnect ddp_disconnect_wrapper |
617 | #define ddp_shutdown ddp_shutdown_wrapper |
618 | #define ddp_abort ddp_abort_wrapper |
619 | #define ddp_ioctl ddp_ioctl_wrapper |
620 | #define ddp_stat ddp_stat_wrapper |
621 | #define ddp_peeraddr ddp_peeraddr_wrapper |
622 | #define ddp_sockaddr ddp_sockaddr_wrapper |
623 | #define ddp_rcvd ddp_rcvd_wrapper |
624 | #define ddp_recvoob ddp_recvoob_wrapper |
625 | #define ddp_send ddp_send_wrapper |
626 | #define ddp_sendoob ddp_sendoob_wrapper |
627 | #define ddp_purgeif ddp_purgeif_wrapper |
628 | |
629 | const struct pr_usrreqs ddp_usrreqs = { |
630 | .pr_attach = ddp_attach, |
631 | .pr_detach = ddp_detach, |
632 | .pr_accept = ddp_accept, |
633 | .pr_bind = ddp_bind, |
634 | .pr_listen = ddp_listen, |
635 | .pr_connect = ddp_connect, |
636 | .pr_connect2 = ddp_connect2, |
637 | .pr_disconnect = ddp_disconnect, |
638 | .pr_shutdown = ddp_shutdown, |
639 | .pr_abort = ddp_abort, |
640 | .pr_ioctl = ddp_ioctl, |
641 | .pr_stat = ddp_stat, |
642 | .pr_peeraddr = ddp_peeraddr, |
643 | .pr_sockaddr = ddp_sockaddr, |
644 | .pr_rcvd = ddp_rcvd, |
645 | .pr_recvoob = ddp_recvoob, |
646 | .pr_send = ddp_send, |
647 | .pr_sendoob = ddp_sendoob, |
648 | .pr_purgeif = ddp_purgeif, |
649 | }; |
650 | |
651 | static int |
652 | sysctl_net_atalk_ddp_stats(SYSCTLFN_ARGS) |
653 | { |
654 | |
655 | return (NETSTAT_SYSCTL(ddpstat_percpu, DDP_NSTATS)); |
656 | } |
657 | |
658 | /* |
659 | * Sysctl for DDP variables. |
660 | */ |
661 | SYSCTL_SETUP(sysctl_net_atalk_ddp_setup, "sysctl net.atalk.ddp subtree setup" ) |
662 | { |
663 | |
664 | sysctl_createv(clog, 0, NULL, NULL, |
665 | CTLFLAG_PERMANENT, |
666 | CTLTYPE_NODE, "atalk" , NULL, |
667 | NULL, 0, NULL, 0, |
668 | CTL_NET, PF_APPLETALK, CTL_EOL); |
669 | sysctl_createv(clog, 0, NULL, NULL, |
670 | CTLFLAG_PERMANENT, |
671 | CTLTYPE_NODE, "ddp" , |
672 | SYSCTL_DESCR("DDP related settings" ), |
673 | NULL, 0, NULL, 0, |
674 | CTL_NET, PF_APPLETALK, ATPROTO_DDP, CTL_EOL); |
675 | |
676 | sysctl_createv(clog, 0, NULL, NULL, |
677 | CTLFLAG_PERMANENT, |
678 | CTLTYPE_STRUCT, "stats" , |
679 | SYSCTL_DESCR("DDP statistics" ), |
680 | sysctl_net_atalk_ddp_stats, 0, NULL, 0, |
681 | CTL_NET, PF_APPLETALK, ATPROTO_DDP, CTL_CREATE, |
682 | CTL_EOL); |
683 | } |
684 | |