2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1995 Apple Computer, Inc.
26 * Created, March 17, 1997 by Tuyen Nguyen for MacOSX.
29 #include <sys/errno.h>
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <machine/spl.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
36 #include <sys/filedesc.h>
37 #include <sys/fcntl.h>
39 #include <sys/ioctl.h>
40 #include <sys/malloc.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
43 #include <sys/ioccom.h>
45 #include <sys/sysctl.h>
49 #include <netat/sysglue.h>
50 #include <netat/appletalk.h>
51 #include <netat/ddp.h>
52 #include <netat/at_pcb.h>
53 #include <netat/at_var.h>
54 #include <netat/routing_tables.h>
55 #include <netat/debug.h>
57 extern struct atpcb ddp_head
;
60 ddp_putmsg(gref_t
*gref
, gbuf_t
*m
),
61 elap_wput(gref_t
*gref
, gbuf_t
*m
),
62 atp_wput(gref_t
*gref
, gbuf_t
*m
),
63 asp_wput(gref_t
*gref
, gbuf_t
*m
),
65 aurp_wput(gref_t
*gref
, gbuf_t
*m
),
67 adsp_wput(gref_t
*gref
, gbuf_t
*m
);
69 void atalk_putnext(gref_t
*gref
, gbuf_t
*m
);
70 static int gref_close(gref_t
*gref
);
72 SYSCTL_DECL(_net_appletalk
);
74 SYSCTL_STRUCT(_net_appletalk
, OID_AUTO
, debug
, CTLFLAG_WR
,
75 &dbgBits
, dbgBits
, "AppleTalk Debug Flags");
76 volatile int RouterMix
= RT_MIX_DEFAULT
; /* default for nbr of ppsec */
77 SYSCTL_INT(_net_appletalk
, OID_AUTO
, routermix
, CTLFLAG_WR
,
78 &RouterMix
, 0, "Appletalk RouterMix");
79 at_ddp_stats_t at_ddp_stats
; /* DDP statistics */
80 SYSCTL_STRUCT(_net_appletalk
, OID_AUTO
, ddpstats
, CTLFLAG_RD
,
81 &at_ddp_stats
, at_ddp_stats
, "AppleTalk DDP Stats");
85 static void gref_wput(gref
, m
)
89 switch (gref
->proto
) {
91 ddp_putmsg(gref
, m
); break;
93 elap_wput(gref
, m
); break;
95 atp_wput(gref
, m
); break;
97 asp_wput(gref
, m
); break;
100 aurp_wput(gref
, m
); break;
103 adsp_wput(gref
, m
); break;
105 if (gbuf_type(m
) == MSG_IOCTL
) {
106 gbuf_freem(gbuf_cont(m
));
108 ((ioc_t
*)gbuf_rptr(m
))->ioc_rval
= -1;
109 ((ioc_t
*)gbuf_rptr(m
))->ioc_error
= EPROTO
;
110 gbuf_set_type(m
, MSG_IOCNAK
);
111 atalk_putnext(gref
, m
);
121 int _ATsocket(proto
, err
, proc
)
129 /* make sure the specified protocol id is valid */
132 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
133 BSD-style socket interface. */
142 #ifdef APPLETALK_DEBUG
143 kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err
);
148 /* allocate a protocol channel */
149 if ((*err
= gref_alloc(&gref
)) != 0) {
150 #ifdef APPLETALK_DEBUG
151 kprintf("_ATsocket: error gref_open =%d\n", *err
);
156 gref
->pid
= ((struct proc
*)proc
)->p_pid
;
158 /* open the specified protocol */
159 switch (gref
->proto
) {
161 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
162 BSD-style socket interface. */
165 *err
= atp_open(gref
, 1); break;
167 *err
= asp_open(gref
); break;
170 *err
= aurp_open(gref
); break;
173 *err
= adsp_open(gref
); break;
176 /* create the descriptor for the channel */
178 #ifdef APPLETALK_DEBUG
179 kprintf("_ATsocket: open failed for %d proto; err = %d\n",
182 gref
->proto
= ATPROTO_NONE
;
184 if (*err
|| (*err
= atalk_openref(gref
, &fd
, proc
))) {
185 #ifdef APPLETALK_DEBUG
186 kprintf("_ATsocket: error atalk_openref =%d\n", *err
);
188 (void)gref_close(gref
);
192 kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd);
197 int _ATgetmsg(fd
, ctlptr
, datptr
, flags
, err
, proc
)
208 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) == 0) {
209 switch (gref
->proto
) {
211 rc
= ASPgetmsg(gref
, ctlptr
, datptr
, flags
, err
);
215 rc
= AURPgetmsg(err
);
219 *err
= EPROTONOSUPPORT
;
224 /* kprintf("_ATgetmsg: return=%d\n", *err);*/
228 int _ATputmsg(fd
, ctlptr
, datptr
, flags
, err
, proc
)
239 if ((*err
= atalk_getref(0, fd
, &gref
, proc
)) == 0) {
240 switch (gref
->proto
) {
242 rc
= ASPputmsg(gref
, ctlptr
, datptr
, flags
, err
); break;
244 *err
= EPROTONOSUPPORT
; break;
248 /* kprintf("_ATputmsg: return=%d\n", *err); */
252 int _ATclose(fp
, proc
)
261 if ((err
= atalk_closeref(fp
, &gref
)) == 0) {
262 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
263 (void)gref_close(gref
);
264 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
270 int _ATrw(fp
, rw
, uio
, ext
)
276 int s
, err
, len
, clen
= 0, res
;
278 gbuf_t
*m
, *mhead
, *mprev
;
280 if ((err
= atalk_getref(fp
, 0, &gref
, 0)) != 0)
283 if ((len
= uio
->uio_resid
) == 0)
286 ATDISABLE(s
, gref
->lock
);
288 if (rw
== UIO_READ
) {
289 KERNEL_DEBUG(DBG_ADSP_ATRW
, 0, gref
, len
, gref
->rdhead
, 0);
290 while ((gref
->errno
== 0) && ((mhead
= gref
->rdhead
) == 0)) {
291 gref
->sevents
|= POLLMSG
;
292 err
= tsleep(&gref
->event
, PSOCK
| PCATCH
, "AT read", 0);
293 gref
->sevents
&= ~POLLMSG
;
295 ATENABLE(s
, gref
->lock
);
298 KERNEL_DEBUG(DBG_ADSP_ATRW
, 1, gref
, gref
->rdhead
, mhead
, gbuf_next(mhead
));
302 ATENABLE(s
, gref
->lock
);
305 if ((gref
->rdhead
= gbuf_next(mhead
)) == 0)
308 KERNEL_DEBUG(DBG_ADSP_ATRW
, 2, gref
, gref
->rdhead
, mhead
, gbuf_next(mhead
));
310 ATENABLE(s
, gref
->lock
);
312 //##### LD TEST 08/05
313 // simple_lock(&gref->lock);
315 gbuf_next(mhead
) = 0;
317 for (mprev
=0, m
=mhead
; m
&& len
; len
-=clen
) {
318 if ((clen
= gbuf_len(m
)) > 0) {
321 uio
->uio_rw
= UIO_READ
;
322 if ((res
= uiomove((caddr_t
)gbuf_rptr(m
),
324 KERNEL_DEBUG(DBG_ADSP_ATRW
, 3, m
, clen
,
328 if (gbuf_len(m
) > len
) {
337 KERNEL_DEBUG(DBG_ADSP_ATRW
, 4, m
, gbuf_len(m
), mprev
, gref
->rdhead
);
339 gbuf_cont(mprev
) = 0;
342 ATDISABLE(s
, gref
->lock
);
343 if (gref
->rdhead
== 0)
345 gbuf_next(m
) = gref
->rdhead
;
347 ATENABLE(s
, gref
->lock
);
352 // simple_unlock(&gref->lock);
354 if (gref
->writeable
) {
355 while (!(*gref
->writeable
)(gref
)) {
356 /* flow control on, wait to be enabled to write */
357 gref
->sevents
|= POLLSYNC
;
358 err
= tsleep(&gref
->event
, PSOCK
| PCATCH
, "AT write", 0);
359 gref
->sevents
&= ~POLLSYNC
;
361 ATENABLE(s
, gref
->lock
);
367 ATENABLE(s
, gref
->lock
);
369 /* allocate a buffer to copy in the write data */
370 if ((m
= gbuf_alloc(AT_WR_OFFSET
+len
, PRI_MED
)) == 0)
372 gbuf_rinc(m
,AT_WR_OFFSET
);
375 /* copy in the write data */
376 uio
->uio_rw
= UIO_WRITE
;
377 if ((res
= uiomove((caddr_t
)gbuf_rptr(m
), len
, uio
))) {
378 #ifdef APPLETALK_DEBUG
379 kprintf("_ATrw: UIO_WRITE: res=%d\n", res
);
385 /* forward the write data to the appropriate protocol module */
392 int _ATread(fp
, uio
, cred
)
399 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
400 stat
= _ATrw(fp
, UIO_READ
, uio
, 0);
401 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
405 int _ATwrite(fp
, uio
, cred
)
413 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
414 stat
= _ATrw(fp
, UIO_WRITE
, uio
, 0);
415 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
420 /* Most of the processing from _ATioctl, so that it can be called
421 from the new ioctl code */
422 int at_ioctl(gref
, cmd
, arg
)
424 register caddr_t arg
;
431 /* error if not for us */
432 if ((cmd
& 0xffff) != 0xff99)
435 /* copy in ioc command info */
437 kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n",
438 ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len,
439 gref->lock, gref->event);
441 if ((err
= copyin((caddr_t
)arg
,
442 (caddr_t
)&ioccmd
, sizeof(ioccmd_t
))) != 0) {
443 #ifdef APPLETALK_DEBUG
444 kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err
,
445 (caddr_t
)arg
, (caddr_t
)&ioccmd
, sizeof(ioccmd_t
));
450 /* allocate a buffer to create an ioc command */
451 if ((m
= gbuf_alloc(sizeof(ioc_t
), PRI_HI
)) == 0)
453 gbuf_wset(m
,sizeof(ioc_t
));
454 gbuf_set_type(m
, MSG_IOCTL
);
456 /* create the ioc command */
458 if ((gbuf_cont(m
) = gbuf_alloc(ioccmd
.ic_len
, PRI_HI
)) == 0) {
460 #ifdef APPLETALK_DEBUG
461 kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS
);
465 gbuf_wset(gbuf_cont(m
),ioccmd
.ic_len
);
466 if ((err
= copyin((caddr_t
)ioccmd
.ic_dp
,
467 (caddr_t
)gbuf_rptr(gbuf_cont(m
)), ioccmd
.ic_len
)) != 0) {
472 ioc
= (ioc_t
*)gbuf_rptr(m
);
473 ioc
->ioc_cmd
= ioccmd
.ic_cmd
;
474 ioc
->ioc_count
= ioccmd
.ic_len
;
478 /* send the ioc command to the appropriate recipient */
481 /* wait for the ioc ack */
482 ATDISABLE(s
, gref
->lock
);
483 while ((m
= gref
->ichead
) == 0) {
484 gref
->sevents
|= POLLPRI
;
485 #ifdef APPLETALK_DEBUG
486 kprintf("sleep gref = 0x%x\n", (unsigned)gref
);
488 err
= tsleep(&gref
->iocevent
, PSOCK
| PCATCH
, "AT ioctl", 0);
489 gref
->sevents
&= ~POLLPRI
;
491 ATENABLE(s
, gref
->lock
);
492 #ifdef APPLETALK_DEBUG
493 kprintf("at_ioctl: EINTR\n");
500 if (gbuf_next(m
) == m
) /* error case */
503 gref
->ichead
= gbuf_next(m
);
505 ATENABLE(s
, gref
->lock
);
507 #ifdef APPLETALK_DEBUG
508 kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n",
511 /* process the ioc response */
512 ioc
= (ioc_t
*)gbuf_rptr(m
);
513 if ((err
= ioc
->ioc_error
) == 0) {
514 ioccmd
.ic_timout
= ioc
->ioc_rval
;
516 mdata
= gbuf_cont(m
);
517 if (mdata
&& ioccmd
.ic_dp
) {
518 ioccmd
.ic_len
= gbuf_msgsize(mdata
);
519 for (len
=0; mdata
; mdata
=gbuf_cont(mdata
)) {
520 if ((err
= copyout((caddr_t
)gbuf_rptr(mdata
),
521 (caddr_t
)&ioccmd
.ic_dp
[len
], gbuf_len(mdata
))) < 0) {
522 #ifdef APPLETALK_DEBUG
523 kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
524 len
, err
, (caddr_t
)gbuf_rptr(mdata
),
525 (caddr_t
)&ioccmd
.ic_dp
[len
], gbuf_len(mdata
));
529 len
+= gbuf_len(mdata
);
532 if ((err
= copyout((caddr_t
)&ioccmd
,
533 (caddr_t
)arg
, sizeof(ioccmd_t
))) != 0) {
534 #ifdef APPLETALK_DEBUG
535 kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n",
536 err
, &ioccmd
, arg
, sizeof(ioccmd_t
));
544 /*kprintf("at_ioctl: I_done=%d\n", err);*/
548 int _ATioctl(fp
, cmd
, arg
, proc
)
551 register caddr_t arg
;
557 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
558 if ((err
= atalk_getref(fp
, 0, &gref
, 0)) != 0) {
559 #ifdef APPLETALK_DEBUG
560 kprintf("_ATioctl: atalk_getref err = %d\n", err
);
564 err
= at_ioctl(gref
, cmd
, arg
);
566 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
571 int _ATselect(fp
, which
, proc
)
579 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
580 err
= atalk_getref(fp
, 0, &gref
, 0);
581 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
586 ATDISABLE(s
, gref
->lock
);
587 if (which
== FREAD
) {
588 if (gref
->rdhead
|| (gref
->readable
&& (*gref
->readable
)(gref
)))
591 gref
->sevents
|= POLLIN
;
592 selrecord(proc
, &gref
->si
);
595 else if (which
== POLLOUT
) {
596 if (gref
->writeable
) {
597 if ((*gref
->writeable
)(gref
))
600 gref
->sevents
|= POLLOUT
;
601 selrecord(proc
, &gref
->si
);
606 ATENABLE(s
, gref
->lock
);
612 void atalk_putnext(gref
, m
)
618 ATDISABLE(s
, gref
->lock
);
620 /* *** potential leak? *** */
623 switch (gbuf_type(m
)) {
627 gbuf_next(gref
->ichead
) = m
;
630 if (gref
->sevents
& POLLPRI
) {
631 #ifdef APPLETALK_DEBUG
632 kprintf("wakeup gref = 0x%x\n", (unsigned)gref
);
634 thread_wakeup(&gref
->iocevent
);
639 /* *** this processing was moved to atalk_notify *** */
640 panic("atalk_putnext receved MSG_ERROR");
647 gbuf_next(gref
->rdtail
) = m
;
651 if (gref
->sevents
& POLLMSG
) {
652 gref
->sevents
&= ~POLLMSG
;
653 thread_wakeup(&gref
->event
);
655 if (gref
->sevents
& POLLIN
) {
656 gref
->sevents
&= ~POLLIN
;
657 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
658 selwakeup(&gref
->si
);
659 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
663 } /* switch gbuf_type(m) */
665 ATENABLE(s
, gref
->lock
);
666 } /* atalk_putnext */
668 void atalk_enablew(gref
)
671 if (gref
->sevents
& POLLSYNC
)
672 thread_wakeup(&gref
->event
);
675 void atalk_flush(gref
)
680 ATDISABLE(s
, gref
->lock
);
682 gbuf_freel(gref
->rdhead
);
686 gbuf_freel(gref
->ichead
);
689 ATENABLE(s
, gref
->lock
);
693 * Notify an appletalk user of an asynchronous error;
694 * just wake up so that he can collect error status.
696 void atalk_notify(gref
, errno
)
697 register gref_t
*gref
;
701 ATDISABLE(s
, gref
->lock
);
703 if (gref
->atpcb_socket
) {
705 This section is patterned after udp_notify() in
708 gref
->atpcb_socket
->so_error
= errno
;
709 sorwakeup(gref
->atpcb_socket
);
710 sowwakeup(gref
->atpcb_socket
);
712 /* for ATP, ASP, and ADSP */
713 if (gref
->errno
== 0) {
715 /* clear out data waiting to be read */
717 gbuf_freel(gref
->rdhead
);
721 if (gref
->sevents
& POLLMSG
) {
722 gref
->sevents
&= ~POLLMSG
;
723 thread_wakeup(&gref
->event
);
726 if (gref
->sevents
& POLLIN
) {
727 gref
->sevents
&= ~POLLIN
;
728 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
729 selwakeup(&gref
->si
);
730 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
734 ATENABLE(s
, gref
->lock
);
737 void atalk_notify_sel(gref
)
742 ATDISABLE(s
, gref
->lock
);
743 if (gref
->sevents
& POLLIN
) {
744 gref
->sevents
&= ~POLLIN
;
745 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
746 selwakeup(&gref
->si
);
747 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
749 ATENABLE(s
, gref
->lock
);
752 int atalk_peek(gref
, event
)
754 unsigned char *event
;
758 ATDISABLE(s
, gref
->lock
);
760 *event
= *gbuf_rptr(gref
->rdhead
);
764 ATENABLE(s
, gref
->lock
);
769 static gbuf_t
*trace_msg
;
771 void atalk_settrace(str
, p1
, p2
, p3
, p4
, p5
)
778 sprintf(trace_buf
, str
, p1
, p2
, p3
, p4
, p5
);
779 len
= strlen(trace_buf
);
780 #ifdef APPLETALK_DEBUG
781 kprintf("atalk_settrace: gbufalloc size=%d\n", len
+1);
783 if ((m
= gbuf_alloc(len
+1, PRI_MED
)) == 0)
786 strcpy(gbuf_rptr(m
), trace_buf
);
788 for (nextm
=trace_msg
; gbuf_cont(nextm
); nextm
=gbuf_cont(nextm
)) ;
789 gbuf_cont(nextm
) = m
;
794 void atalk_gettrace(m
)
798 gbuf_cont(m
) = trace_msg
;
803 #define GREF_PER_BLK 32
804 static gref_t
*gref_free_list
= 0;
806 int gref_alloc(grefp
)
809 extern gbuf_t
*atp_resource_m
;
812 gref_t
*gref
, *gref_array
;
814 *grefp
= (gref_t
*)NULL
;
816 ATDISABLE(s
, refall_lock
);
817 if (gref_free_list
== 0) {
818 ATENABLE(s
, refall_lock
);
819 #ifdef APPLETALK_DEBUG
820 kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK
*sizeof(gref_t
));
822 if ((m
= gbuf_alloc(GREF_PER_BLK
*sizeof(gref_t
),PRI_HI
)) == 0)
824 bzero(gbuf_rptr(m
), GREF_PER_BLK
*sizeof(gref_t
));
825 gref_array
= (gref_t
*)gbuf_rptr(m
);
826 for (i
=0; i
< GREF_PER_BLK
-1; i
++)
827 gref_array
[i
].atpcb_next
= (gref_t
*)&gref_array
[i
+1];
828 ATDISABLE(s
, refall_lock
);
829 gbuf_cont(m
) = atp_resource_m
;
831 gref_array
[i
].atpcb_next
= gref_free_list
;
832 gref_free_list
= (gref_t
*)&gref_array
[0];
835 gref
= gref_free_list
;
836 gref_free_list
= gref
->atpcb_next
;
837 ATENABLE(s
, refall_lock
);
838 ATLOCKINIT(gref
->lock
);
839 //### LD Test 08/05/98
840 // simple_lock_init(&gref->lock);
841 ATEVENTINIT(gref
->event
);
842 ATEVENTINIT(gref
->iocevent
);
844 /* *** just for now *** */
845 gref
->atpcb_socket
= (struct socket
*)NULL
;
851 static int gref_close(gref
)
856 switch (gref
->proto
) {
858 /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
859 BSD-style socket interface. */
862 rc
= atp_close(gref
, 1); break;
864 rc
= asp_close(gref
); break;
867 rc
= aurp_close(gref
); break;
871 rc
= adsp_close(gref
); break;
879 selthreadclear(&gref
->si
);
881 /* from original gref_free() */
882 ATDISABLE(s
, refall_lock
);
883 bzero((char *)gref
, sizeof(gref_t
));
884 gref
->atpcb_next
= gref_free_list
;
885 gref_free_list
= gref
;
886 ATENABLE(s
, refall_lock
);
895 *** Some to be replaced with mbuf routines, some to be re-written
896 as mbuf routines (and moved to kern/uicp_mbuf.c or sys/mbuf.h?).
902 * LD 5/12/97 Added for MacOSX, defines a m_clattach function that:
903 * "Allocates an mbuf structure and attaches an external cluster."
906 struct mbuf
*m_clattach(extbuf
, extfree
, extsize
, extarg
, wait
)
915 if ((m
= m_gethdr(wait
, MSG_DATA
)) == NULL
)
918 m
->m_ext
.ext_buf
= extbuf
;
919 m
->m_ext
.ext_free
= extfree
;
920 m
->m_ext
.ext_size
= extsize
;
921 m
->m_ext
.ext_arg
= extarg
;
922 m
->m_ext
.ext_refs
.forward
=
923 m
->m_ext
.ext_refs
.backward
= &m
->m_ext
.ext_refs
;
931 Used as the "free" routine for over-size clusters allocated using
935 void m_lgbuf_free(buf
, size
, arg
)
937 int size
, arg
; /* not needed, but they're in m_free() */
943 Used to allocate an mbuf when there is the possibility that it may
944 need to be larger than the size of a standard cluster.
947 struct mbuf
*m_lgbuf_alloc(size
, wait
)
952 /* If size is too large, allocate a cluster, otherwise, use the
953 standard mbuf allocation routines.*/
954 if (size
> MCLBYTES
) {
957 (buf
= (void *)_MALLOC(size
, M_MCLUST
,
958 (wait
)? M_WAITOK
: M_NOWAIT
))) {
962 (m
= m_clattach(buf
, m_lgbuf_free
, size
, 0,
963 (wait
)? M_WAIT
: M_DONTWAIT
))) {
968 m
= m_gethdr(((wait
)? M_WAIT
: M_DONTWAIT
), MSG_DATA
);
969 if (m
&& (size
> MHLEN
)) {
970 MCLGET(m
, ((wait
)? M_WAIT
: M_DONTWAIT
));
971 if (!(m
->m_flags
& M_EXT
)) {
979 } /* m_lgbuf_alloc */
982 gbuf_alloc() is a wrapper for m_lgbuf_alloc(), which is used to
983 allocate an mbuf when there is the possibility that it may need
984 to be larger than the size of a standard cluster.
986 gbuf_alloc() sets the mbuf lengths, unlike the standard mbuf routines.
989 gbuf_t
*gbuf_alloc_wait(size
, wait
)
992 gbuf_t
*m
= (gbuf_t
*)m_lgbuf_alloc(size
, wait
);
994 /* Standard mbuf allocation routines assume that the caller
995 will set the size. */
997 (struct mbuf
*)m
->m_pkthdr
.len
= size
;
998 (struct mbuf
*)m
->m_len
= size
;
1009 for (size
=0; m
; m
=gbuf_cont(m
))
1010 size
+= gbuf_len(m
);
1014 int append_copy(m1
, m2
, wait
)
1015 struct mbuf
*m1
, *m2
;
1018 if ((!(m1
->m_flags
& M_EXT
)) && (!(m2
->m_flags
& M_EXT
)) &&
1019 (m_trailingspace(m1
) >= m2
->m_len
)) {
1020 /* splat the data from one into the other */
1021 bcopy(mtod(m2
, caddr_t
), mtod(m1
, caddr_t
) + m1
->m_len
,
1023 m1
->m_len
+= m2
->m_len
;
1024 if (m1
->m_flags
& M_PKTHDR
)
1025 m1
->m_pkthdr
.len
+= m2
->m_len
;
1028 if ((m1
->m_next
= m_copym(m2
, 0, m2
->m_len
,
1029 (wait
)? M_WAIT
: M_DONTWAIT
)) == NULL
)
1035 Copy an mbuf chain, referencing existing external storage, if any.
1036 Leave space for a header in the new chain, if the space has been
1037 left in the origin chain.
1039 struct mbuf
*copy_pkt(mlist
, pad
)
1040 struct mbuf
*mlist
; /* the mbuf chain to be copied */
1041 int pad
; /* hint as to how long the header might be
1042 If pad is < 0, leave the same amount of space
1043 as there was in the original. */
1049 len
= m_leadingspace(mlist
);
1051 len
= min(pad
, m_leadingspace(mlist
));
1053 /* preserve space for the header at the beginning of the mbuf */
1055 mlist
->m_data
-= (len
);
1056 mlist
->m_len
+= (len
);
1057 if (mlist
->m_flags
& M_PKTHDR
)
1058 mlist
->m_pkthdr
.len
+= (len
);
1059 new_m
= m_copym(mlist
, 0, M_COPYALL
, M_DONTWAIT
);
1063 new_m
= m_copym(mlist
, 0, M_COPYALL
, M_DONTWAIT
);
1068 void gbuf_linkb(m1
, m2
)
1072 while (gbuf_cont(m1
) != 0)
1077 void gbuf_linkpkt(m1
, m2
)
1081 while (gbuf_next(m1
) != 0)
1091 while ((tmp_m
= m
) != 0) {
1093 gbuf_next(tmp_m
) = 0;
1099 /* free empty mbufs at the front of the chain */
1100 gbuf_t
*gbuf_strip(m
)
1105 while (m
&& gbuf_len(m
) == 0) {
1113 /**************************************/
1115 int ddp_adjmsg(m
, len
)
1120 gbuf_t
*curr_m
, *prev_m
;
1122 if (m
== (gbuf_t
*)0)
1126 for (curr_m
=m
; curr_m
;) {
1127 buf_len
= gbuf_len(curr_m
);
1128 if (len
< buf_len
) {
1129 gbuf_rinc(curr_m
,len
);
1133 gbuf_rinc(curr_m
,buf_len
);
1134 if ((curr_m
= gbuf_cont(curr_m
)) == 0) {
1140 } else if (len
< 0) {
1143 for (curr_m
=m
; gbuf_cont(curr_m
);
1144 prev_m
=curr_m
, curr_m
=gbuf_cont(curr_m
)) ;
1145 buf_len
= gbuf_len(curr_m
);
1146 if (len
< buf_len
) {
1147 gbuf_wdec(curr_m
,len
);
1152 gbuf_cont(prev_m
) = 0;
1162 * The message chain, m is grown in size by len contiguous bytes.
1163 * If len is non-negative, len bytes are added to the
1164 * end of the gbuf_t chain. If len is negative, the
1165 * bytes are added to the front. ddp_growmsg only adds bytes to
1166 * message blocks of the same type.
1167 * It returns a pointer to the new gbuf_t on sucess, 0 on failure.
1170 gbuf_t
*ddp_growmsg(mp
, len
)
1176 if ((m
= mp
) == (gbuf_t
*) 0)
1177 return ((gbuf_t
*) 0);
1181 if ((d
= gbuf_alloc(len
, PRI_MED
)) == 0)
1182 return ((gbuf_t
*) 0);
1183 gbuf_set_type(d
, gbuf_type(m
));
1185 /* link in new gbuf_t */
1194 if ((count
= gbuf_msgsize(m
)) < 0)
1195 return ((gbuf_t
*) 0);
1196 /* find end of chain */
1197 for ( ; m
; m
= gbuf_cont(m
)) {
1198 if (gbuf_len(m
) >= count
)
1200 count
-= gbuf_len(m
);
1202 /* m now points to gbuf_t to add to */
1203 if ((d
= gbuf_alloc(len
, PRI_MED
)) == 0)
1204 return ((gbuf_t
*) 0);
1205 gbuf_set_type(d
, gbuf_type(m
));
1206 /* link in new gbuf_t */
1207 gbuf_cont(d
) = gbuf_cont(m
);
1215 * return the MSG_IOCACK/MSG_IOCNAK. Note that the same message
1216 * block is used as the vehicle, and that if there is an error return,
1217 * then linked blocks are lopped off. BEWARE of multiple references.
1218 * Used by other appletalk modules, so it is not static!
1221 void ioc_ack(errno
, m
, gref
)
1224 register gref_t
*gref
;
1226 ioc_t
*iocbp
= (ioc_t
*)gbuf_rptr(m
);
1228 /*kprintf("ioc_ack: m=%x gref=%x errno=%d\n", m, gref, errno);*/
1229 if ((iocbp
->ioc_error
= errno
) != 0)
1230 { /* errno != 0, then there is an error, get rid of linked blocks! */
1233 gbuf_freem(gbuf_cont(m
));
1236 gbuf_set_type(m
, MSG_IOCNAK
);
1237 iocbp
->ioc_count
= 0; /* only make zero length if error */
1238 iocbp
->ioc_rval
= -1;
1240 gbuf_set_type(m
, MSG_IOCACK
);
1242 atalk_putnext(gref
, m
);