]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/sys_glue.c
edb15b3fe37d84e42124a069061522e9793b7d6e
[apple/xnu.git] / bsd / netat / sys_glue.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1995 Apple Computer, Inc.
30 *
31 * Change Log:
32 * Created, March 17, 1997 by Tuyen Nguyen for MacOSX.
33 */
34
35 #include <sys/errno.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <machine/spl.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/proc.h>
42 #include <sys/filedesc.h>
43 #include <sys/fcntl.h>
44 #include <sys/file_internal.h>
45 #include <sys/mbuf.h>
46 #include <sys/ioctl.h>
47 #include <sys/malloc.h>
48 #include <kern/locks.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/ioccom.h>
52 #include <sys/uio_internal.h>
53
54 #include <sys/sysctl.h>
55
56 #include <net/if.h>
57
58 #include <netat/sysglue.h>
59 #include <netat/appletalk.h>
60 #include <netat/ddp.h>
61 #include <netat/at_pcb.h>
62 #include <netat/at_var.h>
63 #include <netat/routing_tables.h>
64 #include <netat/debug.h>
65
66 extern struct atpcb ddp_head;
67 extern lck_mtx_t * atalk_mutex;
68
69 extern void
70 ddp_putmsg(gref_t *gref, gbuf_t *m),
71 elap_wput(gref_t *gref, gbuf_t *m),
72 atp_wput(gref_t *gref, gbuf_t *m),
73 asp_wput(gref_t *gref, gbuf_t *m),
74 #ifdef AURP_SUPPORT
75 aurp_wput(gref_t *gref, gbuf_t *m),
76 #endif
77 adsp_wput(gref_t *gref, gbuf_t *m);
78
79 int atp_free_cluster_timeout_set = 0;
80
81
82 void atalk_putnext(gref_t *gref, gbuf_t *m);
83 /* bms: make gref_close non static so its callable from kernel */
84 int gref_close(gref_t *gref);
85
86 SYSCTL_DECL(_net_appletalk);
87 dbgBits_t dbgBits;
88 SYSCTL_STRUCT(_net_appletalk, OID_AUTO, debug, CTLFLAG_WR,
89 &dbgBits, dbgBits, "AppleTalk Debug Flags");
90 volatile int RouterMix = RT_MIX_DEFAULT; /* default for nbr of ppsec */
91 SYSCTL_INT(_net_appletalk, OID_AUTO, routermix, CTLFLAG_WR,
92 (int *)&RouterMix, 0, "Appletalk RouterMix");
93 at_ddp_stats_t at_ddp_stats; /* DDP statistics */
94 SYSCTL_STRUCT(_net_appletalk, OID_AUTO, ddpstats, CTLFLAG_RD,
95 &at_ddp_stats, at_ddp_stats, "AppleTalk DDP Stats");
96
97 static void ioccmd_t_32_to_64( ioccmd_t *from_p, user_ioccmd_t *to_p );
98 static void ioccmd_t_64_to_32( user_ioccmd_t *from_p, ioccmd_t *to_p );
99
100 atlock_t refall_lock;
101
102 caddr_t atp_free_cluster_list = 0;
103
104 void gref_wput(gref, m)
105 gref_t *gref;
106 gbuf_t *m;
107 {
108 switch (gref->proto) {
109 case ATPROTO_DDP:
110 ddp_putmsg(gref, m); break;
111 case ATPROTO_LAP:
112 elap_wput(gref, m); break;
113 case ATPROTO_ATP:
114 atp_wput(gref, m); break;
115 case ATPROTO_ASP:
116 asp_wput(gref, m); break;
117 #ifdef AURP_SUPPORT
118 case ATPROTO_AURP:
119 aurp_wput(gref, m); break;
120 #endif
121 case ATPROTO_ADSP:
122 adsp_wput(gref, m); break;
123 case ATPROTO_NONE:
124 if (gbuf_type(m) == MSG_IOCTL) {
125 gbuf_freem(gbuf_cont(m));
126 gbuf_cont(m) = 0;
127 ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
128 ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTOTYPE;
129 gbuf_set_type(m, MSG_IOCNAK);
130 atalk_putnext(gref, m);
131 } else
132 gbuf_freem(m);
133 break;
134 default:
135 gbuf_freem(m);
136 break;
137 }
138 }
139
140 int _ATsocket(proto, err, proc)
141 int proto;
142 int *err;
143 void *proc;
144 {
145 int fd;
146 gref_t *gref;
147
148 /* make sure the specified protocol id is valid */
149 switch (proto) {
150
151 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
152 BSD-style socket interface. */
153
154 case ATPROTO_ATP:
155 case ATPROTO_ASP:
156 #ifdef AURP_SUPPORT
157 case ATPROTO_AURP:
158 #endif
159 case ATPROTO_ADSP:
160 break;
161 default:
162 *err = EPROTOTYPE;
163 #ifdef APPLETALK_DEBUG
164 kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err);
165 #endif
166 return -1;
167 }
168
169 /* allocate a protocol channel */
170 if ((*err = gref_alloc(&gref)) != 0) {
171 #ifdef APPLETALK_DEBUG
172 kprintf("_ATsocket: error gref_open =%d\n", *err);
173 #endif
174 return -1;
175 }
176 gref->proto = proto;
177 gref->pid = proc_pid((struct proc *)proc);
178
179 /* open the specified protocol */
180 switch (gref->proto) {
181
182 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
183 BSD-style socket interface. */
184
185 case ATPROTO_ATP:
186 *err = atp_open(gref, 1); break;
187 case ATPROTO_ASP:
188 *err = asp_open(gref); break;
189 #ifdef AURP_SUPPORT
190 case ATPROTO_AURP:
191 *err = aurp_open(gref); break;
192 #endif
193 case ATPROTO_ADSP:
194 *err = adsp_open(gref); break;
195 }
196
197 /* create the descriptor for the channel */
198 if (*err) {
199 #ifdef APPLETALK_DEBUG
200 kprintf("_ATsocket: open failed for %d proto; err = %d\n",
201 gref->proto, *err);
202 #endif
203 gref->proto = ATPROTO_NONE;
204 }
205 if (*err || (*err = atalk_openref(gref, &fd, proc))) {
206 #ifdef APPLETALK_DEBUG
207 kprintf("_ATsocket: error atalk_openref =%d\n", *err);
208 #endif
209 (void)gref_close(gref);
210 return -1;
211 }
212 /*
213 kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd);
214 */
215 return fd;
216 } /* _ATsocket */
217
218 int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc)
219 int fd;
220 strbuf_t *ctlptr;
221 strbuf_t *datptr;
222 int *flags;
223 int *err;
224 void *proc;
225 {
226 int rc = -1;
227 gref_t *gref;
228
229 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) == 0) {
230 switch (gref->proto) {
231 case ATPROTO_ASP:
232 rc = ASPgetmsg(gref, ctlptr, datptr, NULL, flags, err);
233 break;
234 case ATPROTO_AURP:
235 #ifdef AURP_SUPPORT
236 rc = AURPgetmsg(err);
237 break;
238 #endif
239 default:
240 *err = EPROTONOSUPPORT;
241 break;
242 }
243 file_drop(fd);
244 }
245
246 /* kprintf("_ATgetmsg: return=%d\n", *err);*/
247 return rc;
248 }
249
250 int _ATputmsg(fd, ctlptr, datptr, flags, err, proc)
251 int fd;
252 strbuf_t *ctlptr;
253 strbuf_t *datptr;
254 int flags;
255 int *err;
256 void *proc;
257 {
258 int rc = -1;
259 gref_t *gref;
260
261 if ((*err = atalk_getref(0, fd, &gref, proc, 1)) == 0) {
262 switch (gref->proto) {
263 case ATPROTO_ASP:
264 rc = ASPputmsg(gref, ctlptr, datptr, NULL, flags, err); break;
265 default:
266 *err = EPROTONOSUPPORT; break;
267 }
268 file_drop(fd);
269 }
270
271 /* kprintf("_ATputmsg: return=%d\n", *err); */
272 return rc;
273 }
274
275 int _ATclose(fg, proc)
276 struct fileglob *fg;
277 struct proc *proc;
278 {
279 int err;
280 gref_t *gref;
281
282 if ((err = atalk_closeref(fg, &gref)) == 0) {
283 atalk_lock();
284 (void)gref_close(gref);
285 atalk_unlock();
286 }
287
288 return err;
289 }
290
291 int _ATrw(fp, rw, uio, p)
292 void *fp;
293 enum uio_rw rw;
294 struct uio *uio;
295 struct proc *p;
296 {
297 int s, err, len, clen = 0, res;
298 gref_t *gref;
299 gbuf_t *m, *mhead, *mprev;
300
301 /* no need to get/drop iocount as the fp already has one */
302 if ((err = atalk_getref_locked(fp, 0, &gref, p, 1)) != 0)
303 return err;
304
305 // LP64todo - fix this!
306 if ((len = uio_resid(uio)) == 0)
307 return 0;
308
309 ATDISABLE(s, gref->lock);
310
311 if (rw == UIO_READ) {
312 KERNEL_DEBUG(DBG_ADSP_ATRW, 0, gref, len, gref->rdhead, 0);
313 while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) {
314 gref->sevents |= POLLMSG;
315 err = msleep(&gref->event, atalk_mutex, PSOCK | PCATCH, "AT read", 0);
316 gref->sevents &= ~POLLMSG;
317 if (err != 0) {
318 ATENABLE(s, gref->lock);
319 return err;
320 }
321 KERNEL_DEBUG(DBG_ADSP_ATRW, 1, gref, gref->rdhead, mhead, gbuf_next(mhead));
322 }
323
324 if (gref->errno) {
325 ATENABLE(s, gref->lock);
326 return EPIPE;
327 }
328 if ((gref->rdhead = gbuf_next(mhead)) == 0)
329 gref->rdtail = 0;
330
331 KERNEL_DEBUG(DBG_ADSP_ATRW, 2, gref, gref->rdhead, mhead, gbuf_next(mhead));
332
333 ATENABLE(s, gref->lock);
334
335 //##### LD TEST 08/05
336 // simple_lock(&gref->lock);
337
338 gbuf_next(mhead) = 0;
339
340 for (mprev=0, m=mhead; m && len; len-=clen) {
341 if ((clen = gbuf_len(m)) > 0) {
342 if (clen > len)
343 clen = len;
344 uio->uio_rw = UIO_READ;
345 if ((res = uiomove((caddr_t)gbuf_rptr(m),
346 clen, uio))) {
347 KERNEL_DEBUG(DBG_ADSP_ATRW, 3, m, clen,
348 len, gbuf_cont(m));
349 break;
350 }
351 if (gbuf_len(m) > len) {
352 gbuf_rinc(m,clen);
353 break;
354 }
355 }
356 mprev = m;
357 m = gbuf_cont(m);
358 }
359 if (m) {
360 KERNEL_DEBUG(DBG_ADSP_ATRW, 4, m, gbuf_len(m), mprev, gref->rdhead);
361 if (mprev)
362 gbuf_cont(mprev) = 0;
363 else
364 mhead = 0;
365 ATDISABLE(s, gref->lock);
366 if (gref->rdhead == 0)
367 gref->rdtail = m;
368 gbuf_next(m) = gref->rdhead;
369 gref->rdhead = m;
370 ATENABLE(s, gref->lock);
371 }
372 if (mhead)
373 gbuf_freem(mhead);
374 //### LD TEST
375 // simple_unlock(&gref->lock);
376 } else {
377 if (gref->writeable) {
378 while (!(*gref->writeable)(gref)) {
379 /* flow control on, wait to be enabled to write */
380 gref->sevents |= POLLSYNC;
381 err = msleep(&gref->event, atalk_mutex, PSOCK | PCATCH, "AT write", 0);
382 gref->sevents &= ~POLLSYNC;
383 if (err != 0) {
384 ATENABLE(s, gref->lock);
385 return err;
386 }
387 }
388 }
389
390 ATENABLE(s, gref->lock);
391
392 /* allocate a buffer to copy in the write data */
393 if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0)
394 return ENOBUFS;
395 gbuf_rinc(m,AT_WR_OFFSET);
396 gbuf_wset(m,len);
397
398 /* copy in the write data */
399 uio->uio_rw = UIO_WRITE;
400 if ((res = uiomove((caddr_t)gbuf_rptr(m), len, uio))) {
401 #ifdef APPLETALK_DEBUG
402 kprintf("_ATrw: UIO_WRITE: res=%d\n", res);
403 #endif
404 gbuf_freeb(m);
405 return EIO;
406 }
407
408 /* forward the write data to the appropriate protocol module */
409 gref_wput(gref, m);
410 }
411
412 return 0;
413 } /* _ATrw */
414
415 int _ATread(fp, uio, cred, flags, p)
416 struct fileproc *fp;
417 struct uio *uio;
418 void *cred;
419 int flags;
420 struct proc *p;
421 {
422 int stat;
423
424 atalk_lock();
425 stat = _ATrw(fp, UIO_READ, uio, p);
426 atalk_unlock();
427 return stat;
428 }
429
430 int _ATwrite(fp, uio, cred, flags, p)
431 struct fileproc *fp;
432 struct uio *uio;
433 void *cred;
434 int flags;
435 struct proc *p;
436 {
437 int stat;
438
439 atalk_lock();
440 stat = _ATrw(fp, UIO_WRITE, uio, p);
441 atalk_unlock();
442
443 return stat;
444 }
445
446 /* Most of the processing from _ATioctl, so that it can be called
447 from the new ioctl code */
448 /* bms: update to be callable from kernel */
449 int at_ioctl(gref_t *gref, u_long cmd, caddr_t arg, int fromKernel)
450 {
451 int s, err = 0, len;
452 u_int size;
453 gbuf_t *m, *mdata;
454 ioc_t *ioc;
455 user_addr_t user_arg;
456 user_ioccmd_t user_ioccmd;
457 boolean_t is64bit;
458
459 /* error if not for us */
460 if ((cmd & 0xffff) != 0xff99)
461 return EOPNOTSUPP;
462
463 size = IOCPARM_LEN(cmd);
464 if (size != sizeof(user_addr_t))
465 return EINVAL;
466
467 user_arg = *((user_addr_t *)arg);
468
469 /* copy in ioc command info */
470 is64bit = proc_is64bit(current_proc());
471 if (fromKernel) {
472 ioccmd_t tmp;
473 bcopy (CAST_DOWN(caddr_t, user_arg), &tmp, sizeof (tmp));
474 ioccmd_t_32_to_64(&tmp, &user_ioccmd);
475 }
476 else {
477 if (is64bit) {
478 err = copyin(user_arg, (caddr_t)&user_ioccmd, sizeof(user_ioccmd));
479 }
480 else {
481 ioccmd_t tmp;
482 err = copyin(user_arg, (caddr_t)&tmp, sizeof(tmp));
483 ioccmd_t_32_to_64(&tmp, &user_ioccmd);
484 }
485 if (err != 0) {
486 #ifdef APPLETALK_DEBUG
487 kprintf("at_ioctl: err = %d, copyin(%llx, %x, %d)\n", err,
488 user_arg, (caddr_t)&user_ioccmd, sizeof(user_ioccmd));
489 #endif
490 return err;
491 }
492 }
493
494 /* allocate a buffer to create an ioc command
495 first mbuf contains ioc command */
496 if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
497 return ENOBUFS;
498 gbuf_wset(m, sizeof(ioc_t)); /* mbuf->m_len */
499 gbuf_set_type(m, MSG_IOCTL); /* mbuf->m_type */
500
501 /* create the ioc command
502 second mbuf contains the actual ASP command */
503 if (user_ioccmd.ic_len) {
504 if ((gbuf_cont(m) = gbuf_alloc(user_ioccmd.ic_len, PRI_HI)) == 0) {
505 gbuf_freem(m);
506 #ifdef APPLETALK_DEBUG
507 kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS);
508 #endif
509 return ENOBUFS;
510 }
511 gbuf_wset(gbuf_cont(m), user_ioccmd.ic_len); /* mbuf->m_len */
512 if (fromKernel)
513 bcopy (CAST_DOWN(caddr_t, user_ioccmd.ic_dp), gbuf_rptr(gbuf_cont(m)), user_ioccmd.ic_len);
514 else {
515 if ((err = copyin(user_ioccmd.ic_dp, (caddr_t)gbuf_rptr(gbuf_cont(m)), user_ioccmd.ic_len)) != 0) {
516 gbuf_freem(m);
517 return err;
518 }
519 }
520 }
521 ioc = (ioc_t *) gbuf_rptr(m);
522 ioc->ioc_cmd = user_ioccmd.ic_cmd;
523 ioc->ioc_count = user_ioccmd.ic_len;
524 ioc->ioc_error = 0;
525 ioc->ioc_rval = 0;
526
527 /* send the ioc command to the appropriate recipient */
528 gref_wput(gref, m);
529
530 /* wait for the ioc ack */
531 ATDISABLE(s, gref->lock);
532 while ((m = gref->ichead) == 0) {
533 gref->sevents |= POLLPRI;
534 #ifdef APPLETALK_DEBUG
535 kprintf("sleep gref = 0x%x\n", (unsigned)gref);
536 #endif
537 err = msleep(&gref->iocevent, atalk_mutex, PSOCK | PCATCH, "AT ioctl", 0);
538 gref->sevents &= ~POLLPRI;
539 if (err != 0) {
540 ATENABLE(s, gref->lock);
541 #ifdef APPLETALK_DEBUG
542 kprintf("at_ioctl: EINTR\n");
543 #endif
544 return err;
545 }
546 }
547
548 /* PR-2224797 */
549 if (gbuf_next(m) == m) /* error case */
550 gbuf_next(m) = 0;
551
552 gref->ichead = gbuf_next(m);
553
554 ATENABLE(s, gref->lock);
555
556 #ifdef APPLETALK_DEBUG
557 kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n",
558 (unsigned)gref);
559 #endif
560
561 /* process the ioc response */
562 ioc = (ioc_t *) gbuf_rptr(m);
563 if ((err = ioc->ioc_error) == 0) {
564 user_ioccmd.ic_timout = ioc->ioc_rval;
565 user_ioccmd.ic_len = 0;
566 mdata = gbuf_cont(m);
567 if (mdata && user_ioccmd.ic_dp) {
568 user_ioccmd.ic_len = gbuf_msgsize(mdata);
569 for (len = 0; mdata; mdata = gbuf_cont(mdata)) {
570 if (fromKernel)
571 bcopy (gbuf_rptr(mdata), CAST_DOWN(caddr_t, (user_ioccmd.ic_dp + len)), gbuf_len(mdata));
572 else {
573 if ((err = copyout((caddr_t)gbuf_rptr(mdata), (user_ioccmd.ic_dp + len), gbuf_len(mdata))) < 0) {
574 #ifdef APPLETALK_DEBUG
575 kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
576 len, err, (caddr_t)gbuf_rptr(mdata), (caddr_t)&user_ioccmd.ic_dp[len], gbuf_len(mdata));
577 #endif
578 goto l_done;
579 }
580 }
581 len += gbuf_len(mdata);
582 }
583 }
584
585 if (fromKernel) {
586 ioccmd_t tmp;
587 ioccmd_t_64_to_32(&user_ioccmd, &tmp);
588 bcopy (&tmp, CAST_DOWN(caddr_t, user_arg), sizeof(tmp));
589 }
590 else {
591 if (is64bit) {
592 err = copyout((caddr_t)&user_ioccmd, user_arg, sizeof(user_ioccmd));
593 }
594 else {
595 ioccmd_t tmp;
596 ioccmd_t_64_to_32(&user_ioccmd, &tmp);
597 err = copyout((caddr_t)&tmp, user_arg, sizeof(tmp));
598 }
599 if (err != 0) {
600 goto l_done;
601 }
602 }
603 }
604
605 l_done:
606 gbuf_freem(m);
607 /*kprintf("at_ioctl: I_done=%d\n", err);*/
608 return err;
609 } /* at_ioctl */
610
611 int _ATioctl(fp, cmd, arg, proc)
612 void *fp;
613 u_long cmd;
614 register caddr_t arg;
615 void *proc;
616 {
617 int err;
618 gref_t *gref;
619
620 atalk_lock();
621 /* No need to get a reference on fp as it already has one */
622 if ((err = atalk_getref_locked(fp, 0, &gref, 0, 0)) != 0) {
623 #ifdef APPLETALK_DEBUG
624 kprintf("_ATioctl: atalk_getref err = %d\n", err);
625 #endif
626 }
627 else
628 err = at_ioctl(gref, cmd, arg, 0);
629
630 atalk_unlock();
631
632 return err;
633 }
634
635 int _ATselect(fp, which, wql, proc)
636 struct fileproc *fp;
637 int which;
638 void * wql;
639 struct proc *proc;
640 {
641 int s, err, rc = 0;
642 gref_t *gref;
643
644 /* Radar 4128949: Drop the proc_fd lock here to avoid lock inversion issues with the other AT calls
645 * select() is already holding a reference on the fd, so it won't go away during the time it is unlocked.
646 */
647 proc_fdunlock(proc);
648
649 atalk_lock();
650 /* no need to drop the iocount as select covers that */
651 err = atalk_getref_locked(fp, 0, &gref, 0, 0);
652 atalk_unlock();
653
654 /* Safe to re-grab the proc_fdlock at that point */
655 proc_fdlock(proc);
656 if (err != 0)
657 rc = 1;
658 else {
659 ATDISABLE(s, gref->lock);
660 if (which == FREAD) {
661 if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
662 rc = 1;
663 else {
664 gref->sevents |= POLLIN;
665 selrecord(proc, &gref->si, wql);
666 }
667 }
668 else if (which == POLLOUT) {
669 if (gref->writeable) {
670 if ((*gref->writeable)(gref))
671 rc = 1;
672 else {
673 gref->sevents |= POLLOUT;
674 selrecord(proc, &gref->si, wql);
675 }
676 } else
677 rc = 1;
678 }
679 ATENABLE(s, gref->lock);
680 }
681
682 return rc;
683 }
684
685 int _ATkqfilter(fp, kn, p)
686 struct fileproc *fp;
687 struct knote *kn;
688 struct proc *p;
689 {
690 return (EOPNOTSUPP);
691 }
692
693 void atalk_putnext(gref, m)
694 gref_t *gref;
695 gbuf_t *m;
696 {
697 int s;
698
699 ATDISABLE(s, gref->lock);
700
701 /* *** potential leak? *** */
702 gbuf_next(m) = 0;
703
704 switch (gbuf_type(m)) {
705 case MSG_IOCACK:
706 case MSG_IOCNAK:
707 if (gref->ichead)
708 gbuf_next(gref->ichead) = m;
709 else {
710 gref->ichead = m;
711 if (gref->sevents & POLLPRI) {
712 #ifdef APPLETALK_DEBUG
713 kprintf("wakeup gref = 0x%x\n", (unsigned)gref);
714 #endif
715 wakeup(&gref->iocevent);
716 }
717 }
718 break;
719 case MSG_ERROR:
720 /* *** this processing was moved to atalk_notify *** */
721 panic("atalk_putnext receved MSG_ERROR");
722 break;
723 default:
724 if (gref->errno)
725 gbuf_freem(m);
726 else
727 if (gref->rdhead) {
728 gbuf_next(gref->rdtail) = m;
729 gref->rdtail = m;
730 } else {
731 gref->rdhead = m;
732 if (gref->sevents & POLLMSG) {
733 gref->sevents &= ~POLLMSG;
734 wakeup(&gref->event);
735 }
736 if (gref->sevents & POLLIN) {
737 gref->sevents &= ~POLLIN;
738 selwakeup(&gref->si);
739 }
740 gref->rdtail = m;
741 }
742 } /* switch gbuf_type(m) */
743
744 ATENABLE(s, gref->lock);
745 } /* atalk_putnext */
746
747 void atalk_enablew(gref)
748 gref_t *gref;
749 {
750 if (gref->sevents & POLLSYNC)
751 wakeup(&gref->event);
752 }
753
754 void atalk_flush(gref)
755 gref_t *gref;
756 {
757 int s;
758
759 ATDISABLE(s, gref->lock);
760 if (gref->rdhead) {
761 gbuf_freel(gref->rdhead);
762 gref->rdhead = 0;
763 }
764 if (gref->ichead) {
765 gbuf_freel(gref->ichead);
766 gref->ichead = 0;
767 }
768 ATENABLE(s, gref->lock);
769 }
770
771 /*
772 * Notify an appletalk user of an asynchronous error;
773 * just wake up so that he can collect error status.
774 */
775 void atalk_notify(gref, errno)
776 register gref_t *gref;
777 int errno;
778 {
779 int s;
780 ATDISABLE(s, gref->lock);
781
782 if (gref->atpcb_socket) {
783 /* For DDP --
784 This section is patterned after udp_notify() in
785 netinet/udp_usrreq.c
786 */
787 gref->atpcb_socket->so_error = errno;
788 sorwakeup(gref->atpcb_socket);
789 sowwakeup(gref->atpcb_socket);
790 } else {
791 /* for ATP, ASP, and ADSP */
792 if (gref->errno == 0) {
793 gref->errno = errno;
794 /* clear out data waiting to be read */
795 if (gref->rdhead) {
796 gbuf_freel(gref->rdhead);
797 gref->rdhead = 0;
798 }
799 /* blocked read */
800 if (gref->sevents & POLLMSG) {
801 gref->sevents &= ~POLLMSG;
802 wakeup(&gref->event);
803 }
804 /* select */
805 if (gref->sevents & POLLIN) {
806 gref->sevents &= ~POLLIN;
807 selwakeup(&gref->si);
808 }
809 }
810 }
811 ATENABLE(s, gref->lock);
812 } /* atalk_notify */
813
814 void atalk_notify_sel(gref)
815 gref_t *gref;
816 {
817 int s;
818
819 ATDISABLE(s, gref->lock);
820 if (gref->sevents & POLLIN) {
821 gref->sevents &= ~POLLIN;
822 selwakeup(&gref->si);
823 }
824 ATENABLE(s, gref->lock);
825 }
826
827 int atalk_peek(gref, event)
828 gref_t *gref;
829 unsigned char *event;
830 {
831 int s, rc;
832
833 ATDISABLE(s, gref->lock);
834 if (gref->rdhead) {
835 *event = *gbuf_rptr(gref->rdhead);
836 rc = 0;
837 } else
838 rc = -1;
839 ATENABLE(s, gref->lock);
840
841 return rc;
842 }
843
844 static gbuf_t *trace_msg;
845
846 void atalk_settrace(str, p1, p2, p3, p4, p5)
847 char *str;
848 {
849 int len;
850 gbuf_t *m, *nextm;
851 char trace_buf[256];
852
853 sprintf(trace_buf, str, p1, p2, p3, p4, p5);
854 len = strlen(trace_buf);
855 #ifdef APPLETALK_DEBUG
856 kprintf("atalk_settrace: gbufalloc size=%d\n", len+1);
857 #endif
858 if ((m = gbuf_alloc(len+1, PRI_MED)) == 0)
859 return;
860 gbuf_wset(m,len);
861 strcpy(gbuf_rptr(m), trace_buf);
862 if (trace_msg) {
863 for (nextm=trace_msg; gbuf_cont(nextm); nextm=gbuf_cont(nextm)) ;
864 gbuf_cont(nextm) = m;
865 } else
866 trace_msg = m;
867 }
868
869 void atalk_gettrace(m)
870 gbuf_t *m;
871 {
872 if (trace_msg) {
873 gbuf_cont(m) = trace_msg;
874 trace_msg = 0;
875 }
876 }
877
878 #define GREF_PER_BLK 32
879 static gref_t *gref_free_list = 0;
880
881 int gref_alloc(grefp)
882 gref_t **grefp;
883 {
884 extern gbuf_t *atp_resource_m;
885 int i, s;
886 gbuf_t *m;
887 gref_t *gref, *gref_array;
888
889 *grefp = (gref_t *)NULL;
890
891 ATDISABLE(s, refall_lock);
892 if (gref_free_list == 0) {
893 ATENABLE(s, refall_lock);
894 #ifdef APPLETALK_DEBUG
895 kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t));
896 #endif
897 if ((m = gbuf_alloc(GREF_PER_BLK*sizeof(gref_t),PRI_HI)) == 0)
898 return ENOBUFS;
899 bzero(gbuf_rptr(m), GREF_PER_BLK*sizeof(gref_t));
900 gref_array = (gref_t *)gbuf_rptr(m);
901 for (i=0; i < GREF_PER_BLK-1; i++)
902 gref_array[i].atpcb_next = (gref_t *)&gref_array[i+1];
903 ATDISABLE(s, refall_lock);
904 gbuf_cont(m) = atp_resource_m;
905 atp_resource_m = m;
906 gref_array[i].atpcb_next = gref_free_list;
907 gref_free_list = (gref_t *)&gref_array[0];
908 }
909
910 gref = gref_free_list;
911 gref_free_list = gref->atpcb_next;
912 ATENABLE(s, refall_lock);
913 ATLOCKINIT(gref->lock);
914 //### LD Test 08/05/98
915 // simple_lock_init(&gref->lock);
916 ATEVENTINIT(gref->event);
917 ATEVENTINIT(gref->iocevent);
918
919 /* *** just for now *** */
920 gref->atpcb_socket = (struct socket *)NULL;
921
922 *grefp = gref;
923 return 0;
924 } /* gref_alloc */
925
926 /* bms: make gref_close callable from kernel */
927 int gref_close(gref_t *gref)
928 {
929 int s, rc;
930
931 switch (gref->proto) {
932
933 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
934 BSD-style socket interface. */
935
936 case ATPROTO_ATP:
937 rc = atp_close(gref, 1); break;
938 case ATPROTO_ASP:
939 rc = asp_close(gref); break;
940 #ifdef AURP_SUPPORT
941 case ATPROTO_AURP:
942 rc = aurp_close(gref); break;
943 break;
944 #endif
945 case ATPROTO_ADSP:
946 rc = adsp_close(gref); break;
947 default:
948 rc = 0;
949 break;
950 }
951
952 if (rc == 0) {
953 atalk_flush(gref);
954 selthreadclear(&gref->si);
955
956 /* from original gref_free() */
957 ATDISABLE(s, refall_lock);
958 bzero((char *)gref, sizeof(gref_t));
959 gref->atpcb_next = gref_free_list;
960 gref_free_list = gref;
961 ATENABLE(s, refall_lock);
962 }
963
964 return rc;
965 }
966 \f
967 /*
968 Buffer Routines
969
970 *** Some to be replaced with mbuf routines, some to be re-written
971 as mbuf routines (and moved to kern/uicp_mbuf.c or sys/mbuf.h?).
972 ***
973
974 */
975
976 /*
977 * LD 5/12/97 Added for MacOSX, defines a m_clattach function that:
978 * "Allocates an mbuf structure and attaches an external cluster."
979 */
980
981 struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait)
982 caddr_t extbuf;
983 void (*extfree)(caddr_t , u_int, caddr_t);
984 u_int extsize;
985 caddr_t extarg;
986 int wait;
987 {
988 struct mbuf *m;
989
990 if ((m = m_gethdr(wait, MSG_DATA)) == NULL)
991 return (NULL);
992
993 m->m_ext.ext_buf = extbuf;
994 m->m_ext.ext_free = extfree;
995 m->m_ext.ext_size = extsize;
996 m->m_ext.ext_arg = extarg;
997 m->m_ext.ext_refs.forward =
998 m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
999 m->m_data = extbuf;
1000 m->m_flags |= M_EXT;
1001
1002 return (m);
1003 }
1004
1005
1006
1007 /*
1008 temp fix for bug 2731148 - until this code is re-written to use standard clusters
1009 Deletes any free clusters on the free list.
1010 */
1011 void atp_delete_free_clusters()
1012 {
1013 caddr_t cluster;
1014 caddr_t cluster_list;
1015
1016
1017 /* check for free clusters on the free_cluster_list to be deleted */
1018 MBUF_LOCK(); /* lock used by mbuf routines */
1019
1020 untimeout(&atp_delete_free_clusters, NULL);
1021 atp_free_cluster_timeout_set = 0;
1022
1023 cluster_list = atp_free_cluster_list;
1024 atp_free_cluster_list = 0;
1025
1026 MBUF_UNLOCK();
1027
1028 while (cluster = cluster_list)
1029 {
1030 cluster_list = *((caddr_t*)cluster);
1031 FREE(cluster, M_MCLUST);
1032 }
1033
1034 }
1035
1036
1037 /*
1038 Used as the "free" routine for over-size clusters allocated using
1039 m_lgbuf_alloc(). Called by m_free while under MBUF_LOCK.
1040 */
1041
1042 void m_lgbuf_free(buf, size, arg)
1043 caddr_t buf;
1044 u_int size;
1045 caddr_t arg; /* not needed, but they're in m_free() */
1046 {
1047 /* FREE(buf, M_MCLUST); - can't free here - called from m_free while under lock */
1048
1049 /* move to free_cluster_list to be deleted later */
1050 caddr_t cluster = (caddr_t)buf;
1051
1052 /* don't need a lock because this is only called called from m_free which */
1053 /* is under MBUF_LOCK */
1054 *((caddr_t*)cluster) = atp_free_cluster_list;
1055 atp_free_cluster_list = cluster;
1056
1057 if (atp_free_cluster_timeout_set == 0)
1058 {
1059 atp_free_cluster_timeout_set = 1;
1060 timeout(&atp_delete_free_clusters, NULL, (1 * HZ));
1061 }
1062 }
1063
1064 /*
1065 Used to allocate an mbuf when there is the possibility that it may
1066 need to be larger than the size of a standard cluster.
1067 */
1068
1069 struct mbuf *m_lgbuf_alloc(size, wait)
1070 int size, wait;
1071 {
1072 struct mbuf *m;
1073
1074 if (atp_free_cluster_list)
1075 atp_delete_free_clusters(); /* delete any free clusters on the free list */
1076
1077 /* If size is too large, allocate a cluster, otherwise, use the
1078 standard mbuf allocation routines.*/
1079 if (size > MCLBYTES) {
1080 void *buf;
1081 if (NULL ==
1082 (buf = (void *)_MALLOC(size, M_MCLUST,
1083 (wait)? M_WAITOK: M_NOWAIT))) {
1084 return(NULL);
1085 }
1086 if (NULL ==
1087 (m = m_clattach(buf, m_lgbuf_free, size, 0,
1088 (wait)? M_WAIT: M_DONTWAIT))) {
1089 m_lgbuf_free(buf, 0, 0);
1090 return(NULL);
1091 }
1092 } else {
1093 m = m_gethdr(((wait)? M_WAIT: M_DONTWAIT), MSG_DATA);
1094 if (m && (size > MHLEN)) {
1095 MCLGET(m, ((wait)? M_WAIT: M_DONTWAIT));
1096 if (!(m->m_flags & M_EXT)) {
1097 (void)m_free(m);
1098 return(NULL);
1099 }
1100 }
1101 }
1102
1103 return(m);
1104 } /* m_lgbuf_alloc */
1105
1106 /*
1107 gbuf_alloc() is a wrapper for m_lgbuf_alloc(), which is used to
1108 allocate an mbuf when there is the possibility that it may need
1109 to be larger than the size of a standard cluster.
1110
1111 gbuf_alloc() sets the mbuf lengths, unlike the standard mbuf routines.
1112 */
1113
1114 gbuf_t *gbuf_alloc_wait(size, wait)
1115 int size, wait;
1116 {
1117 gbuf_t *m = (gbuf_t *)m_lgbuf_alloc(size, wait);
1118
1119 /* Standard mbuf allocation routines assume that the caller
1120 will set the size. */
1121 if (m) {
1122 (struct mbuf *)m->m_pkthdr.len = size;
1123 (struct mbuf *)m->m_len = size;
1124 }
1125
1126 return(m);
1127 }
1128
1129 int gbuf_msgsize(m)
1130 gbuf_t *m;
1131 {
1132 int size;
1133
1134 for (size=0; m; m=gbuf_cont(m))
1135 size += gbuf_len(m);
1136 return size;
1137 }
1138
1139 int append_copy(m1, m2, wait)
1140 struct mbuf *m1, *m2;
1141 int wait;
1142 {
1143 if ((!(m1->m_flags & M_EXT)) && (!(m2->m_flags & M_EXT)) &&
1144 (m_trailingspace(m1) >= m2->m_len)) {
1145 /* splat the data from one into the other */
1146 bcopy(mtod(m2, caddr_t), mtod(m1, caddr_t) + m1->m_len,
1147 (u_int)m2->m_len);
1148 m1->m_len += m2->m_len;
1149 if (m1->m_flags & M_PKTHDR)
1150 m1->m_pkthdr.len += m2->m_len;
1151 return 1;
1152 }
1153 if ((m1->m_next = m_copym(m2, 0, m2->m_len,
1154 (wait)? M_WAIT: M_DONTWAIT)) == NULL)
1155 return 0;
1156 return 1;
1157 } /* append_copy */
1158
1159 /*
1160 Copy an mbuf chain, referencing existing external storage, if any.
1161 Leave space for a header in the new chain, if the space has been
1162 left in the origin chain.
1163 */
1164 struct mbuf *copy_pkt(mlist, pad)
1165 struct mbuf *mlist; /* the mbuf chain to be copied */
1166 int pad; /* hint as to how long the header might be
1167 If pad is < 0, leave the same amount of space
1168 as there was in the original. */
1169 {
1170 struct mbuf *new_m;
1171 int len;
1172
1173 if (pad < 0)
1174 len = m_leadingspace(mlist);
1175 else
1176 len = min(pad, m_leadingspace(mlist));
1177
1178 /* preserve space for the header at the beginning of the mbuf */
1179 if (len) {
1180 mlist->m_data -= (len);
1181 mlist->m_len += (len);
1182 if (mlist->m_flags & M_PKTHDR)
1183 mlist->m_pkthdr.len += (len);
1184 new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT);
1185 m_adj(mlist, len);
1186 m_adj(new_m, len);
1187 } else
1188 new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT);
1189
1190 return(new_m);
1191 }
1192
1193 void gbuf_linkb(m1, m2)
1194 gbuf_t *m1;
1195 gbuf_t *m2;
1196 {
1197 while (gbuf_cont(m1) != 0)
1198 m1 = gbuf_cont(m1);
1199 gbuf_cont(m1) = m2;
1200 }
1201
1202 void gbuf_linkpkt(m1, m2)
1203 gbuf_t *m1;
1204 gbuf_t *m2;
1205 {
1206 while (gbuf_next(m1) != 0)
1207 m1 = gbuf_next(m1);
1208 gbuf_next(m1) = m2;
1209 }
1210
1211 int gbuf_freel(m)
1212 gbuf_t *m;
1213 {
1214 gbuf_t *tmp_m;
1215
1216 while ((tmp_m = m) != 0) {
1217 m = gbuf_next(m);
1218 gbuf_next(tmp_m) = 0;
1219 gbuf_freem(tmp_m);
1220 }
1221 return (0);
1222 }
1223
1224 /* free empty mbufs at the front of the chain */
1225 gbuf_t *gbuf_strip(m)
1226 gbuf_t *m;
1227 {
1228 gbuf_t *tmp_m;
1229
1230 while (m && gbuf_len(m) == 0) {
1231 tmp_m = m;
1232 m = gbuf_cont(m);
1233 gbuf_freeb(tmp_m);
1234 }
1235 return(m);
1236 }
1237 \f
1238 /**************************************/
1239
1240 int ddp_adjmsg(m, len)
1241 gbuf_t *m;
1242 int len;
1243 {
1244 int buf_len;
1245 gbuf_t *curr_m, *prev_m;
1246
1247 if (m == (gbuf_t *)0)
1248 return 0;
1249
1250 if (len > 0) {
1251 for (curr_m=m; curr_m;) {
1252 buf_len = gbuf_len(curr_m);
1253 if (len < buf_len) {
1254 gbuf_rinc(curr_m,len);
1255 return 1;
1256 }
1257 len -= buf_len;
1258 gbuf_rinc(curr_m,buf_len);
1259 if ((curr_m = gbuf_cont(curr_m)) == 0) {
1260 gbuf_freem(m);
1261 return 0;
1262 }
1263 }
1264
1265 } else if (len < 0) {
1266 len = -len;
1267 l_cont: prev_m = 0;
1268 for (curr_m=m; gbuf_cont(curr_m);
1269 prev_m=curr_m, curr_m=gbuf_cont(curr_m)) ;
1270 buf_len = gbuf_len(curr_m);
1271 if (len < buf_len) {
1272 gbuf_wdec(curr_m,len);
1273 return 1;
1274 }
1275 if (prev_m == 0)
1276 return 0;
1277 gbuf_cont(prev_m) = 0;
1278 gbuf_freeb(curr_m);
1279 len -= buf_len;
1280 goto l_cont;
1281
1282 } else
1283 return 1;
1284 }
1285
1286 /*
1287 * The message chain, m is grown in size by len contiguous bytes.
1288 * If len is non-negative, len bytes are added to the
1289 * end of the gbuf_t chain. If len is negative, the
1290 * bytes are added to the front. ddp_growmsg only adds bytes to
1291 * message blocks of the same type.
1292 * It returns a pointer to the new gbuf_t on sucess, 0 on failure.
1293 */
1294
1295 gbuf_t *ddp_growmsg(mp, len)
1296 gbuf_t *mp;
1297 int len;
1298 {
1299 gbuf_t *m, *d;
1300
1301 if ((m = mp) == (gbuf_t *) 0)
1302 return ((gbuf_t *) 0);
1303
1304 if (len <= 0) {
1305 len = -len;
1306 if ((d = gbuf_alloc(len, PRI_MED)) == 0)
1307 return ((gbuf_t *) 0);
1308 gbuf_set_type(d, gbuf_type(m));
1309 gbuf_wset(d,len);
1310 /* link in new gbuf_t */
1311 gbuf_cont(d) = m;
1312 return (d);
1313
1314 } else {
1315 register int count;
1316 /*
1317 * Add to tail.
1318 */
1319 if ((count = gbuf_msgsize(m)) < 0)
1320 return ((gbuf_t *) 0);
1321 /* find end of chain */
1322 for ( ; m; m = gbuf_cont(m)) {
1323 if (gbuf_len(m) >= count)
1324 break;
1325 count -= gbuf_len(m);
1326 }
1327 /* m now points to gbuf_t to add to */
1328 if ((d = gbuf_alloc(len, PRI_MED)) == 0)
1329 return ((gbuf_t *) 0);
1330 gbuf_set_type(d, gbuf_type(m));
1331 /* link in new gbuf_t */
1332 gbuf_cont(d) = gbuf_cont(m);
1333 gbuf_cont(m) = d;
1334 gbuf_wset(d,len);
1335 return (d);
1336 }
1337 }
1338
1339 /*
1340 * return the MSG_IOCACK/MSG_IOCNAK. Note that the same message
1341 * block is used as the vehicle, and that if there is an error return,
1342 * then linked blocks are lopped off. BEWARE of multiple references.
1343 * Used by other appletalk modules, so it is not static!
1344 */
1345
1346 void ioc_ack(errno, m, gref)
1347 int errno;
1348 register gbuf_t *m;
1349 register gref_t *gref;
1350 {
1351 ioc_t *iocbp = (ioc_t *)gbuf_rptr(m);
1352
1353 /*kprintf("ioc_ack: m=%x gref=%x errno=%d\n", m, gref, errno);*/
1354 if ((iocbp->ioc_error = errno) != 0)
1355 { /* errno != 0, then there is an error, get rid of linked blocks! */
1356
1357 if (gbuf_cont(m)) {
1358 gbuf_freem(gbuf_cont(m));
1359 gbuf_cont(m) = 0;
1360 }
1361 gbuf_set_type(m, MSG_IOCNAK);
1362 iocbp->ioc_count = 0; /* only make zero length if error */
1363 iocbp->ioc_rval = -1;
1364 } else
1365 gbuf_set_type(m, MSG_IOCACK);
1366
1367 atalk_putnext(gref, m);
1368 }
1369
1370
1371 static void ioccmd_t_32_to_64( ioccmd_t *from_p, user_ioccmd_t *to_p )
1372 {
1373 to_p->ic_cmd = from_p->ic_cmd;
1374 to_p->ic_timout = from_p->ic_timout;
1375 to_p->ic_len = from_p->ic_len;
1376 to_p->ic_dp = CAST_USER_ADDR_T(from_p->ic_dp);
1377 }
1378
1379
1380 static void ioccmd_t_64_to_32( user_ioccmd_t *from_p, ioccmd_t *to_p )
1381 {
1382 to_p->ic_cmd = from_p->ic_cmd;
1383 to_p->ic_timout = from_p->ic_timout;
1384 to_p->ic_len = from_p->ic_len;
1385 to_p->ic_dp = CAST_DOWN(caddr_t, from_p->ic_dp);
1386 }