2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1995 Apple Computer, Inc.
32 * Created, March 17, 1997 by Tuyen Nguyen for MacOSX.
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>
42 #include <sys/filedesc.h>
43 #include <sys/fcntl.h>
44 #include <sys/file_internal.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>
54 #include <sys/sysctl.h>
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>
66 extern struct atpcb ddp_head
;
67 extern lck_mtx_t
* atalk_mutex
;
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
),
75 aurp_wput(gref_t
*gref
, gbuf_t
*m
),
77 adsp_wput(gref_t
*gref
, gbuf_t
*m
);
79 int atp_free_cluster_timeout_set
= 0;
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
);
86 SYSCTL_DECL(_net_appletalk
);
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");
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
);
100 atlock_t refall_lock
;
102 caddr_t atp_free_cluster_list
= 0;
104 void gref_wput(gref
, m
)
108 switch (gref
->proto
) {
110 ddp_putmsg(gref
, m
); break;
112 elap_wput(gref
, m
); break;
114 atp_wput(gref
, m
); break;
116 asp_wput(gref
, m
); break;
119 aurp_wput(gref
, m
); break;
122 adsp_wput(gref
, m
); break;
124 if (gbuf_type(m
) == MSG_IOCTL
) {
125 gbuf_freem(gbuf_cont(m
));
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
);
140 int _ATsocket(proto
, err
, proc
)
148 /* make sure the specified protocol id is valid */
151 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
152 BSD-style socket interface. */
163 #ifdef APPLETALK_DEBUG
164 kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err
);
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
);
177 gref
->pid
= proc_pid((struct proc
*)proc
);
179 /* open the specified protocol */
180 switch (gref
->proto
) {
182 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
183 BSD-style socket interface. */
186 *err
= atp_open(gref
, 1); break;
188 *err
= asp_open(gref
); break;
191 *err
= aurp_open(gref
); break;
194 *err
= adsp_open(gref
); break;
197 /* create the descriptor for the channel */
199 #ifdef APPLETALK_DEBUG
200 kprintf("_ATsocket: open failed for %d proto; err = %d\n",
203 gref
->proto
= ATPROTO_NONE
;
205 if (*err
|| (*err
= atalk_openref(gref
, &fd
, proc
))) {
206 #ifdef APPLETALK_DEBUG
207 kprintf("_ATsocket: error atalk_openref =%d\n", *err
);
209 (void)gref_close(gref
);
213 kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd);
218 int _ATgetmsg(fd
, ctlptr
, datptr
, flags
, err
, proc
)
229 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) == 0) {
230 switch (gref
->proto
) {
232 rc
= ASPgetmsg(gref
, ctlptr
, datptr
, NULL
, flags
, err
);
236 rc
= AURPgetmsg(err
);
240 *err
= EPROTONOSUPPORT
;
246 /* kprintf("_ATgetmsg: return=%d\n", *err);*/
250 int _ATputmsg(fd
, ctlptr
, datptr
, flags
, err
, proc
)
261 if ((*err
= atalk_getref(0, fd
, &gref
, proc
, 1)) == 0) {
262 switch (gref
->proto
) {
264 rc
= ASPputmsg(gref
, ctlptr
, datptr
, NULL
, flags
, err
); break;
266 *err
= EPROTONOSUPPORT
; break;
271 /* kprintf("_ATputmsg: return=%d\n", *err); */
275 int _ATclose(fg
, proc
)
282 if ((err
= atalk_closeref(fg
, &gref
)) == 0) {
284 (void)gref_close(gref
);
291 int _ATrw(fp
, rw
, uio
, p
)
297 int s
, err
, len
, clen
= 0, res
;
299 gbuf_t
*m
, *mhead
, *mprev
;
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)
305 // LP64todo - fix this!
306 if ((len
= uio_resid(uio
)) == 0)
309 ATDISABLE(s
, gref
->lock
);
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
;
318 ATENABLE(s
, gref
->lock
);
321 KERNEL_DEBUG(DBG_ADSP_ATRW
, 1, gref
, gref
->rdhead
, mhead
, gbuf_next(mhead
));
325 ATENABLE(s
, gref
->lock
);
328 if ((gref
->rdhead
= gbuf_next(mhead
)) == 0)
331 KERNEL_DEBUG(DBG_ADSP_ATRW
, 2, gref
, gref
->rdhead
, mhead
, gbuf_next(mhead
));
333 ATENABLE(s
, gref
->lock
);
335 //##### LD TEST 08/05
336 // simple_lock(&gref->lock);
338 gbuf_next(mhead
) = 0;
340 for (mprev
=0, m
=mhead
; m
&& len
; len
-=clen
) {
341 if ((clen
= gbuf_len(m
)) > 0) {
344 uio
->uio_rw
= UIO_READ
;
345 if ((res
= uiomove((caddr_t
)gbuf_rptr(m
),
347 KERNEL_DEBUG(DBG_ADSP_ATRW
, 3, m
, clen
,
351 if (gbuf_len(m
) > len
) {
360 KERNEL_DEBUG(DBG_ADSP_ATRW
, 4, m
, gbuf_len(m
), mprev
, gref
->rdhead
);
362 gbuf_cont(mprev
) = 0;
365 ATDISABLE(s
, gref
->lock
);
366 if (gref
->rdhead
== 0)
368 gbuf_next(m
) = gref
->rdhead
;
370 ATENABLE(s
, gref
->lock
);
375 // simple_unlock(&gref->lock);
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
;
384 ATENABLE(s
, gref
->lock
);
390 ATENABLE(s
, gref
->lock
);
392 /* allocate a buffer to copy in the write data */
393 if ((m
= gbuf_alloc(AT_WR_OFFSET
+len
, PRI_MED
)) == 0)
395 gbuf_rinc(m
,AT_WR_OFFSET
);
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
);
408 /* forward the write data to the appropriate protocol module */
415 int _ATread(fp
, uio
, cred
, flags
, p
)
425 stat
= _ATrw(fp
, UIO_READ
, uio
, p
);
430 int _ATwrite(fp
, uio
, cred
, flags
, p
)
440 stat
= _ATrw(fp
, UIO_WRITE
, uio
, p
);
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
)
455 user_addr_t user_arg
;
456 user_ioccmd_t user_ioccmd
;
459 /* error if not for us */
460 if ((cmd
& 0xffff) != 0xff99)
463 size
= IOCPARM_LEN(cmd
);
464 if (size
!= sizeof(user_addr_t
))
467 user_arg
= *((user_addr_t
*)arg
);
469 /* copy in ioc command info */
470 is64bit
= proc_is64bit(current_proc());
473 bcopy (CAST_DOWN(caddr_t
, user_arg
), &tmp
, sizeof (tmp
));
474 ioccmd_t_32_to_64(&tmp
, &user_ioccmd
);
478 err
= copyin(user_arg
, (caddr_t
)&user_ioccmd
, sizeof(user_ioccmd
));
482 err
= copyin(user_arg
, (caddr_t
)&tmp
, sizeof(tmp
));
483 ioccmd_t_32_to_64(&tmp
, &user_ioccmd
);
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
));
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)
498 gbuf_wset(m
, sizeof(ioc_t
)); /* mbuf->m_len */
499 gbuf_set_type(m
, MSG_IOCTL
); /* mbuf->m_type */
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) {
506 #ifdef APPLETALK_DEBUG
507 kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS
);
511 gbuf_wset(gbuf_cont(m
), user_ioccmd
.ic_len
); /* mbuf->m_len */
513 bcopy (CAST_DOWN(caddr_t
, user_ioccmd
.ic_dp
), gbuf_rptr(gbuf_cont(m
)), user_ioccmd
.ic_len
);
515 if ((err
= copyin(user_ioccmd
.ic_dp
, (caddr_t
)gbuf_rptr(gbuf_cont(m
)), user_ioccmd
.ic_len
)) != 0) {
521 ioc
= (ioc_t
*) gbuf_rptr(m
);
522 ioc
->ioc_cmd
= user_ioccmd
.ic_cmd
;
523 ioc
->ioc_count
= user_ioccmd
.ic_len
;
527 /* send the ioc command to the appropriate recipient */
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
);
537 err
= msleep(&gref
->iocevent
, atalk_mutex
, PSOCK
| PCATCH
, "AT ioctl", 0);
538 gref
->sevents
&= ~POLLPRI
;
540 ATENABLE(s
, gref
->lock
);
541 #ifdef APPLETALK_DEBUG
542 kprintf("at_ioctl: EINTR\n");
549 if (gbuf_next(m
) == m
) /* error case */
552 gref
->ichead
= gbuf_next(m
);
554 ATENABLE(s
, gref
->lock
);
556 #ifdef APPLETALK_DEBUG
557 kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n",
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
)) {
571 bcopy (gbuf_rptr(mdata
), CAST_DOWN(caddr_t
, (user_ioccmd
.ic_dp
+ len
)), gbuf_len(mdata
));
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
));
581 len
+= gbuf_len(mdata
);
587 ioccmd_t_64_to_32(&user_ioccmd
, &tmp
);
588 bcopy (&tmp
, CAST_DOWN(caddr_t
, user_arg
), sizeof(tmp
));
592 err
= copyout((caddr_t
)&user_ioccmd
, user_arg
, sizeof(user_ioccmd
));
596 ioccmd_t_64_to_32(&user_ioccmd
, &tmp
);
597 err
= copyout((caddr_t
)&tmp
, user_arg
, sizeof(tmp
));
607 /*kprintf("at_ioctl: I_done=%d\n", err);*/
611 int _ATioctl(fp
, cmd
, arg
, proc
)
614 register caddr_t arg
;
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
);
628 err
= at_ioctl(gref
, cmd
, arg
, 0);
635 int _ATselect(fp
, which
, wql
, proc
)
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.
650 /* no need to drop the iocount as select covers that */
651 err
= atalk_getref_locked(fp
, 0, &gref
, 0, 0);
654 /* Safe to re-grab the proc_fdlock at that point */
659 ATDISABLE(s
, gref
->lock
);
660 if (which
== FREAD
) {
661 if (gref
->rdhead
|| (gref
->readable
&& (*gref
->readable
)(gref
)))
664 gref
->sevents
|= POLLIN
;
665 selrecord(proc
, &gref
->si
, wql
);
668 else if (which
== POLLOUT
) {
669 if (gref
->writeable
) {
670 if ((*gref
->writeable
)(gref
))
673 gref
->sevents
|= POLLOUT
;
674 selrecord(proc
, &gref
->si
, wql
);
679 ATENABLE(s
, gref
->lock
);
685 int _ATkqfilter(fp
, kn
, p
)
693 void atalk_putnext(gref
, m
)
699 ATDISABLE(s
, gref
->lock
);
701 /* *** potential leak? *** */
704 switch (gbuf_type(m
)) {
708 gbuf_next(gref
->ichead
) = m
;
711 if (gref
->sevents
& POLLPRI
) {
712 #ifdef APPLETALK_DEBUG
713 kprintf("wakeup gref = 0x%x\n", (unsigned)gref
);
715 wakeup(&gref
->iocevent
);
720 /* *** this processing was moved to atalk_notify *** */
721 panic("atalk_putnext receved MSG_ERROR");
728 gbuf_next(gref
->rdtail
) = m
;
732 if (gref
->sevents
& POLLMSG
) {
733 gref
->sevents
&= ~POLLMSG
;
734 wakeup(&gref
->event
);
736 if (gref
->sevents
& POLLIN
) {
737 gref
->sevents
&= ~POLLIN
;
738 selwakeup(&gref
->si
);
742 } /* switch gbuf_type(m) */
744 ATENABLE(s
, gref
->lock
);
745 } /* atalk_putnext */
747 void atalk_enablew(gref
)
750 if (gref
->sevents
& POLLSYNC
)
751 wakeup(&gref
->event
);
754 void atalk_flush(gref
)
759 ATDISABLE(s
, gref
->lock
);
761 gbuf_freel(gref
->rdhead
);
765 gbuf_freel(gref
->ichead
);
768 ATENABLE(s
, gref
->lock
);
772 * Notify an appletalk user of an asynchronous error;
773 * just wake up so that he can collect error status.
775 void atalk_notify(gref
, errno
)
776 register gref_t
*gref
;
780 ATDISABLE(s
, gref
->lock
);
782 if (gref
->atpcb_socket
) {
784 This section is patterned after udp_notify() in
787 gref
->atpcb_socket
->so_error
= errno
;
788 sorwakeup(gref
->atpcb_socket
);
789 sowwakeup(gref
->atpcb_socket
);
791 /* for ATP, ASP, and ADSP */
792 if (gref
->errno
== 0) {
794 /* clear out data waiting to be read */
796 gbuf_freel(gref
->rdhead
);
800 if (gref
->sevents
& POLLMSG
) {
801 gref
->sevents
&= ~POLLMSG
;
802 wakeup(&gref
->event
);
805 if (gref
->sevents
& POLLIN
) {
806 gref
->sevents
&= ~POLLIN
;
807 selwakeup(&gref
->si
);
811 ATENABLE(s
, gref
->lock
);
814 void atalk_notify_sel(gref
)
819 ATDISABLE(s
, gref
->lock
);
820 if (gref
->sevents
& POLLIN
) {
821 gref
->sevents
&= ~POLLIN
;
822 selwakeup(&gref
->si
);
824 ATENABLE(s
, gref
->lock
);
827 int atalk_peek(gref
, event
)
829 unsigned char *event
;
833 ATDISABLE(s
, gref
->lock
);
835 *event
= *gbuf_rptr(gref
->rdhead
);
839 ATENABLE(s
, gref
->lock
);
844 static gbuf_t
*trace_msg
;
846 void atalk_settrace(str
, p1
, p2
, p3
, p4
, p5
)
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);
858 if ((m
= gbuf_alloc(len
+1, PRI_MED
)) == 0)
861 strcpy(gbuf_rptr(m
), trace_buf
);
863 for (nextm
=trace_msg
; gbuf_cont(nextm
); nextm
=gbuf_cont(nextm
)) ;
864 gbuf_cont(nextm
) = m
;
869 void atalk_gettrace(m
)
873 gbuf_cont(m
) = trace_msg
;
878 #define GREF_PER_BLK 32
879 static gref_t
*gref_free_list
= 0;
881 int gref_alloc(grefp
)
884 extern gbuf_t
*atp_resource_m
;
887 gref_t
*gref
, *gref_array
;
889 *grefp
= (gref_t
*)NULL
;
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
));
897 if ((m
= gbuf_alloc(GREF_PER_BLK
*sizeof(gref_t
),PRI_HI
)) == 0)
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
;
906 gref_array
[i
].atpcb_next
= gref_free_list
;
907 gref_free_list
= (gref_t
*)&gref_array
[0];
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
);
919 /* *** just for now *** */
920 gref
->atpcb_socket
= (struct socket
*)NULL
;
926 /* bms: make gref_close callable from kernel */
927 int gref_close(gref_t
*gref
)
931 switch (gref
->proto
) {
933 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
934 BSD-style socket interface. */
937 rc
= atp_close(gref
, 1); break;
939 rc
= asp_close(gref
); break;
942 rc
= aurp_close(gref
); break;
946 rc
= adsp_close(gref
); break;
954 selthreadclear(&gref
->si
);
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
);
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?).
977 * LD 5/12/97 Added for MacOSX, defines a m_clattach function that:
978 * "Allocates an mbuf structure and attaches an external cluster."
981 struct mbuf
*m_clattach(extbuf
, extfree
, extsize
, extarg
, wait
)
983 void (*extfree
)(caddr_t
, u_int
, caddr_t
);
990 if ((m
= m_gethdr(wait
, MSG_DATA
)) == NULL
)
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
;
1000 m
->m_flags
|= M_EXT
;
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.
1011 void atp_delete_free_clusters()
1014 caddr_t cluster_list
;
1017 /* check for free clusters on the free_cluster_list to be deleted */
1018 MBUF_LOCK(); /* lock used by mbuf routines */
1020 untimeout(&atp_delete_free_clusters
, NULL
);
1021 atp_free_cluster_timeout_set
= 0;
1023 cluster_list
= atp_free_cluster_list
;
1024 atp_free_cluster_list
= 0;
1028 while (cluster
= cluster_list
)
1030 cluster_list
= *((caddr_t
*)cluster
);
1031 FREE(cluster
, M_MCLUST
);
1038 Used as the "free" routine for over-size clusters allocated using
1039 m_lgbuf_alloc(). Called by m_free while under MBUF_LOCK.
1042 void m_lgbuf_free(buf
, size
, arg
)
1045 caddr_t arg
; /* not needed, but they're in m_free() */
1047 /* FREE(buf, M_MCLUST); - can't free here - called from m_free while under lock */
1049 /* move to free_cluster_list to be deleted later */
1050 caddr_t cluster
= (caddr_t
)buf
;
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
;
1057 if (atp_free_cluster_timeout_set
== 0)
1059 atp_free_cluster_timeout_set
= 1;
1060 timeout(&atp_delete_free_clusters
, NULL
, (1 * HZ
));
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.
1069 struct mbuf
*m_lgbuf_alloc(size
, wait
)
1074 if (atp_free_cluster_list
)
1075 atp_delete_free_clusters(); /* delete any free clusters on the free list */
1077 /* If size is too large, allocate a cluster, otherwise, use the
1078 standard mbuf allocation routines.*/
1079 if (size
> MCLBYTES
) {
1082 (buf
= (void *)_MALLOC(size
, M_MCLUST
,
1083 (wait
)? M_WAITOK
: M_NOWAIT
))) {
1087 (m
= m_clattach(buf
, m_lgbuf_free
, size
, 0,
1088 (wait
)? M_WAIT
: M_DONTWAIT
))) {
1089 m_lgbuf_free(buf
, 0, 0);
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
)) {
1104 } /* m_lgbuf_alloc */
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.
1111 gbuf_alloc() sets the mbuf lengths, unlike the standard mbuf routines.
1114 gbuf_t
*gbuf_alloc_wait(size
, wait
)
1117 gbuf_t
*m
= (gbuf_t
*)m_lgbuf_alloc(size
, wait
);
1119 /* Standard mbuf allocation routines assume that the caller
1120 will set the size. */
1122 (struct mbuf
*)m
->m_pkthdr
.len
= size
;
1123 (struct mbuf
*)m
->m_len
= size
;
1134 for (size
=0; m
; m
=gbuf_cont(m
))
1135 size
+= gbuf_len(m
);
1139 int append_copy(m1
, m2
, wait
)
1140 struct mbuf
*m1
, *m2
;
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
,
1148 m1
->m_len
+= m2
->m_len
;
1149 if (m1
->m_flags
& M_PKTHDR
)
1150 m1
->m_pkthdr
.len
+= m2
->m_len
;
1153 if ((m1
->m_next
= m_copym(m2
, 0, m2
->m_len
,
1154 (wait
)? M_WAIT
: M_DONTWAIT
)) == NULL
)
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.
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. */
1174 len
= m_leadingspace(mlist
);
1176 len
= min(pad
, m_leadingspace(mlist
));
1178 /* preserve space for the header at the beginning of the mbuf */
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
);
1188 new_m
= m_copym(mlist
, 0, M_COPYALL
, M_DONTWAIT
);
1193 void gbuf_linkb(m1
, m2
)
1197 while (gbuf_cont(m1
) != 0)
1202 void gbuf_linkpkt(m1
, m2
)
1206 while (gbuf_next(m1
) != 0)
1216 while ((tmp_m
= m
) != 0) {
1218 gbuf_next(tmp_m
) = 0;
1224 /* free empty mbufs at the front of the chain */
1225 gbuf_t
*gbuf_strip(m
)
1230 while (m
&& gbuf_len(m
) == 0) {
1238 /**************************************/
1240 int ddp_adjmsg(m
, len
)
1245 gbuf_t
*curr_m
, *prev_m
;
1247 if (m
== (gbuf_t
*)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
);
1258 gbuf_rinc(curr_m
,buf_len
);
1259 if ((curr_m
= gbuf_cont(curr_m
)) == 0) {
1265 } else if (len
< 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
);
1277 gbuf_cont(prev_m
) = 0;
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.
1295 gbuf_t
*ddp_growmsg(mp
, len
)
1301 if ((m
= mp
) == (gbuf_t
*) 0)
1302 return ((gbuf_t
*) 0);
1306 if ((d
= gbuf_alloc(len
, PRI_MED
)) == 0)
1307 return ((gbuf_t
*) 0);
1308 gbuf_set_type(d
, gbuf_type(m
));
1310 /* link in new gbuf_t */
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
)
1325 count
-= gbuf_len(m
);
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
);
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!
1346 void ioc_ack(errno
, m
, gref
)
1349 register gref_t
*gref
;
1351 ioc_t
*iocbp
= (ioc_t
*)gbuf_rptr(m
);
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! */
1358 gbuf_freem(gbuf_cont(m
));
1361 gbuf_set_type(m
, MSG_IOCNAK
);
1362 iocbp
->ioc_count
= 0; /* only make zero length if error */
1363 iocbp
->ioc_rval
= -1;
1365 gbuf_set_type(m
, MSG_IOCACK
);
1367 atalk_putnext(gref
, m
);
1371 static void ioccmd_t_32_to_64( ioccmd_t
*from_p
, user_ioccmd_t
*to_p
)
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
);
1380 static void ioccmd_t_64_to_32( user_ioccmd_t
*from_p
, ioccmd_t
*to_p
)
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
);