|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1995 Apple Computer, Inc.
24: *
25: * Change Log:
26: * Created, March 17, 1997 by Tuyen Nguyen for MacOSX.
27: */
28:
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>
35: #include <sys/proc.h>
36: #include <sys/filedesc.h>
37: #include <sys/fcntl.h>
38: #include <sys/mbuf.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>
44:
45: #include <sys/sysctl.h>
46:
47: #include <net/if.h>
48:
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>
56:
57: extern struct atpcb ddp_head;
58:
59: extern void
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),
64: #ifdef AURP_SUPPORT
65: aurp_wput(gref_t *gref, gbuf_t *m),
66: #endif
67: adsp_wput(gref_t *gref, gbuf_t *m);
68:
69: void atalk_putnext(gref_t *gref, gbuf_t *m);
70: static int gref_close(gref_t *gref);
71:
72: SYSCTL_DECL(_net_appletalk);
73: dbgBits_t dbgBits;
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:
80: atlock_t refall_lock;
81:
82: static void gref_wput(gref, m)
83: gref_t *gref;
84: gbuf_t *m;
85: {
86: switch (gref->proto) {
87: case ATPROTO_DDP:
88: ddp_putmsg(gref, m); break;
89: case ATPROTO_LAP:
90: elap_wput(gref, m); break;
91: case ATPROTO_ATP:
92: atp_wput(gref, m); break;
93: case ATPROTO_ASP:
94: asp_wput(gref, m); break;
95: #ifdef AURP_SUPPORT
96: case ATPROTO_AURP:
97: aurp_wput(gref, m); break;
98: #endif
99: case ATPROTO_ADSP:
100: adsp_wput(gref, m); break;
101: case ATPROTO_NONE:
102: if (gbuf_type(m) == MSG_IOCTL) {
103: gbuf_freem(gbuf_cont(m));
104: gbuf_cont(m) = 0;
105: ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
106: ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTO;
107: gbuf_set_type(m, MSG_IOCNAK);
108: atalk_putnext(gref, m);
109: } else
110: gbuf_freem(m);
111: break;
112: default:
113: gbuf_freem(m);
114: break;
115: }
116: }
117:
118: int _ATsocket(proto, err, proc)
119: int proto;
120: int *err;
121: void *proc;
122: {
123: int fd;
124: gref_t *gref;
125:
126: /* make sure the specified protocol id is valid */
127: switch (proto) {
128:
129: /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
130: BSD-style socket interface. */
131:
132: case ATPROTO_ATP:
133: case ATPROTO_ASP:
134: case ATPROTO_AURP:
135: case ATPROTO_ADSP:
136: break;
137: default:
138: *err = EPROTOTYPE;
139: #ifdef APPLETALK_DEBUG
140: kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err);
141: #endif
142: return -1;
143: }
144:
145: /* allocate a protocol channel */
146: if ((*err = gref_alloc(&gref)) != 0) {
147: #ifdef APPLETALK_DEBUG
148: kprintf("_ATsocket: error gref_open =%d\n", *err);
149: #endif
150: return -1;
151: }
152: gref->proto = proto;
153: gref->pid = ((struct proc *)proc)->p_pid;
154:
155: /* open the specified protocol */
156: switch (gref->proto) {
157:
158: /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
159: BSD-style socket interface. */
160:
161: case ATPROTO_ATP:
162: *err = atp_open(gref, 1); break;
163: case ATPROTO_ASP:
164: *err = asp_open(gref); break;
165: #ifdef AURP_SUPPORT
166: case ATPROTO_AURP:
167: *err = aurp_open(gref); break;
168: #endif
169: case ATPROTO_ADSP:
170: *err = adsp_open(gref); break;
171: }
172:
173: /* create the descriptor for the channel */
174: if (*err) {
175: #ifdef APPLETALK_DEBUG
176: kprintf("_ATsocket: open failed for %d proto; err = %d\n",
177: gref->proto, *err);
178: #endif
179: gref->proto = ATPROTO_NONE;
180: }
181: if (*err || (*err = atalk_openref(gref, &fd, proc))) {
182: #ifdef APPLETALK_DEBUG
183: kprintf("_ATsocket: error atalk_openref =%d\n", *err);
184: #endif
185: (void)gref_close(gref);
186: return -1;
187: }
188: /*
189: kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd);
190: */
191: return fd;
192: } /* _ATsocket */
193:
194: int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc)
195: int fd;
196: strbuf_t *ctlptr;
197: strbuf_t *datptr;
198: int *flags;
199: int *err;
200: void *proc;
201: {
202: int rc = -1;
203: gref_t *gref;
204:
205: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
206: switch (gref->proto) {
207: case ATPROTO_ASP:
208: rc = ASPgetmsg(gref, ctlptr, datptr, flags, err); break;
209: case ATPROTO_AURP:
210: #ifdef AURP_SUPPORT
211: rc = AURPgetmsg(err); break;
212: #endif
213: default:
214: *err = EPROTONOSUPPORT; break;
215: }
216: }
217:
218:
219: /* kprintf("_ATgetmsg: return=%d\n", *err);*/
220: return rc;
221: }
222:
223: int _ATputmsg(fd, ctlptr, datptr, flags, err, proc)
224: int fd;
225: strbuf_t *ctlptr;
226: strbuf_t *datptr;
227: int flags;
228: int *err;
229: void *proc;
230: {
231: int rc = -1;
232: gref_t *gref;
233:
234: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
235: switch (gref->proto) {
236: case ATPROTO_ASP:
237: rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break;
238: default:
239: *err = EPROTONOSUPPORT; break;
240: }
241: }
242:
243: /* kprintf("_ATputmsg: return=%d\n", *err); */
244: return rc;
245: }
246:
247: int _ATclose(fp, proc)
248: void *fp;
249: void *proc;
250: {
251: int err;
252: gref_t *gref;
253:
254: if ((err = atalk_closeref(fp, &gref)) != 0)
255: return err;
256:
257: (void)gref_close(gref);
258: return 0;
259: }
260:
261: int _ATrw(fp, rw, uio, ext)
262: void *fp;
263: enum uio_rw rw;
264: struct uio *uio;
265: int ext;
266: {
267: int s, err, len, clen = 0, res;
268: gref_t *gref;
269: gbuf_t *m, *mhead, *mprev;
270:
271: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
272: return err;
273:
274: if ((len = uio->uio_resid) == 0)
275: return 0;
276:
277: ATDISABLE(s, gref->lock);
278: if (gref->errno) {
279: ATENABLE(s, gref->lock);
280: return (int)gref->errno;
281: }
282:
283: if (rw == UIO_READ) {
284: KERNEL_DEBUG(DBG_ADSP_ATRW, 0, gref, len, gref->rdhead, 0);
285: while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) {
286: gref->sevents |= POLLMSG;
287: err = tsleep(&gref->event, PSOCK | PCATCH, "AT read", 0);
288: gref->sevents &= ~POLLMSG;
289: if (err != 0) {
290: ATENABLE(s, gref->lock);
291: return err;
292: }
293: KERNEL_DEBUG(DBG_ADSP_ATRW, 1, gref, gref->rdhead, mhead, gbuf_next(mhead));
294: }
295:
296: if (gref->errno) {
297: ATENABLE(s, gref->lock);
298: return EPIPE;
299: }
300: if ((gref->rdhead = gbuf_next(mhead)) == 0)
301: gref->rdtail = 0;
302:
303: KERNEL_DEBUG(DBG_ADSP_ATRW, 2, gref, gref->rdhead, mhead, gbuf_next(mhead));
304:
305: ATENABLE(s, gref->lock);
306:
307: //##### LD TEST 08/05
308: // simple_lock(&gref->lock);
309:
310: gbuf_next(mhead) = 0;
311:
312: for (mprev=0, m=mhead; m && len; len-=clen) {
313: if ((clen = gbuf_len(m)) > 0) {
314: if (clen > len)
315: clen = len;
316: uio->uio_rw = UIO_READ;
317: if ((res = uiomove((caddr_t)gbuf_rptr(m),
318: clen, uio))) {
319: KERNEL_DEBUG(DBG_ADSP_ATRW, 3, m, clen,
320: len, gbuf_cont(m));
321: break;
322: }
323: if (gbuf_len(m) > len) {
324: gbuf_rinc(m,clen);
325: break;
326: }
327: }
328: mprev = m;
329: m = gbuf_cont(m);
330: }
331: if (m) {
332: KERNEL_DEBUG(DBG_ADSP_ATRW, 4, m, gbuf_len(m), mprev, gref->rdhead);
333: if (mprev)
334: gbuf_cont(mprev) = 0;
335: else
336: mhead = 0;
337: ATDISABLE(s, gref->lock);
338: if (gref->rdhead == 0)
339: gref->rdtail = m;
340: gbuf_next(m) = gref->rdhead;
341: gref->rdhead = m;
342: ATENABLE(s, gref->lock);
343: }
344: if (mhead)
345: gbuf_freem(mhead);
346: //### LD TEST
347: // simple_unlock(&gref->lock);
348: } else {
349: if (gref->writeable) {
350: while (!(*gref->writeable)(gref)) {
351: /* flow control on, wait to be enabled to write */
352: gref->sevents |= POLLSYNC;
353: err = tsleep(&gref->event, PSOCK | PCATCH, "AT write", 0);
354: gref->sevents &= ~POLLSYNC;
355: if (err != 0) {
356: ATENABLE(s, gref->lock);
357: return err;
358: }
359: }
360: }
361:
362: ATENABLE(s, gref->lock);
363:
364: /* allocate a buffer to copy in the write data */
365: if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0)
366: return ENOBUFS;
367: gbuf_rinc(m,AT_WR_OFFSET);
368: gbuf_wset(m,len);
369:
370: /* copy in the write data */
371: uio->uio_rw = UIO_WRITE;
372: if ((res = uiomove((caddr_t)gbuf_rptr(m), len, uio))) {
373: #ifdef APPLETALK_DEBUG
374: kprintf("_ATrw: UIO_WRITE: res=%d\n", res);
375: #endif
376: gbuf_freeb(m);
377: return EIO;
378: }
379:
380: /* forward the write data to the appropriate protocol module */
381: gref_wput(gref, m);
382: }
383:
384: return 0;
385: } /* _ATrw */
386:
387: int _ATread(fp, uio, cred)
388: void *fp;
389: struct uio *uio;
390: void *cred;
391: {
392: return _ATrw(fp, UIO_READ, uio, 0);
393: }
394:
395: int _ATwrite(fp, uio, cred)
396: void *fp;
397: struct uio *uio;
398: void *cred;
399: {
400: return _ATrw(fp, UIO_WRITE, uio, 0);
401: }
402:
403: /* Most of the processing from _ATioctl, so that it can be called
404: from the new select code */
405: int at_ioctl(gref, cmd, arg)
406: gref_t *gref;
407: register caddr_t arg;
408: {
409: int s, err = 0, len;
410: gbuf_t *m, *mdata;
411: ioc_t *ioc;
412: ioccmd_t ioccmd;
413:
414: /* error if not for us */
415: if ((cmd & 0xffff) != 0xff99)
416: return EOPNOTSUPP;
417:
418: /* copy in ioc command info */
419: /*
420: kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n",
421: ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len,
422: gref->lock, gref->event);
423: */
424: if ((err = copyin((caddr_t)arg,
425: (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) {
426: #ifdef APPLETALK_DEBUG
427: kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err,
428: (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t));
429: #endif
430: return err;
431: }
432:
433: /* allocate a buffer to create an ioc command */
434: if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
435: return ENOBUFS;
436: gbuf_wset(m,sizeof(ioc_t));
437: gbuf_set_type(m, MSG_IOCTL);
438:
439: /* create the ioc command */
440: if (ioccmd.ic_len) {
441: if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) {
442: gbuf_freem(m);
443: #ifdef APPLETALK_DEBUG
444: kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS);
445: #endif
446: return ENOBUFS;
447: }
448: gbuf_wset(gbuf_cont(m),ioccmd.ic_len);
449: if ((err = copyin((caddr_t)ioccmd.ic_dp,
450: (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) {
451: gbuf_freem(m);
452: return err;
453: }
454: }
455: ioc = (ioc_t *)gbuf_rptr(m);
456: ioc->ioc_cmd = ioccmd.ic_cmd;
457: ioc->ioc_count = ioccmd.ic_len;
458: ioc->ioc_error = 0;
459: ioc->ioc_rval = 0;
460:
461: /* send the ioc command to the appropriate recipient */
462: gref_wput(gref, m);
463:
464: /* wait for the ioc ack */
465: ATDISABLE(s, gref->lock);
466: while ((m = gref->ichead) == 0) {
467: gref->sevents |= POLLPRI;
468: #ifdef APPLETALK_DEBUG
469: kprintf("sleep gref = 0x%x\n", (unsigned)gref);
470: #endif
471: err = tsleep(&gref->iocevent, PSOCK | PCATCH, "AT ioctl", 0);
472: gref->sevents &= ~POLLPRI;
473: if (err != 0) {
474: ATENABLE(s, gref->lock);
475: #ifdef APPLETALK_DEBUG
476: kprintf("at_ioctl: EINTR\n");
477: #endif
478: return err;
479: }
480: }
481:
482: /* PR-2224797 */
483: if (gbuf_next(m) == m) /* error case */
484: gbuf_next(m) = 0;
485:
486: gref->ichead = gbuf_next(m);
487:
488: ATENABLE(s, gref->lock);
489:
490: #ifdef APPLETALK_DEBUG
491: kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n",
492: (unsigned)gref);
493: #endif
494: /* process the ioc response */
495: ioc = (ioc_t *)gbuf_rptr(m);
496: if ((err = ioc->ioc_error) == 0) {
497: ioccmd.ic_timout = ioc->ioc_rval;
498: ioccmd.ic_len = 0;
499: mdata = gbuf_cont(m);
500: if (mdata && ioccmd.ic_dp) {
501: ioccmd.ic_len = gbuf_msgsize(mdata);
502: for (len=0; mdata; mdata=gbuf_cont(mdata)) {
503: if ((err = copyout((caddr_t)gbuf_rptr(mdata),
504: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) {
505: #ifdef APPLETALK_DEBUG
506: kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
507: len, err, (caddr_t)gbuf_rptr(mdata),
508: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata));
509: #endif
510: goto l_done;
511: }
512: len += gbuf_len(mdata);
513: }
514: }
515: if ((err = copyout((caddr_t)&ioccmd,
516: (caddr_t)arg, sizeof(ioccmd_t))) != 0) {
517: #ifdef APPLETALK_DEBUG
518: kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n",
519: err, &ioccmd, arg, sizeof(ioccmd_t));
520: #endif
521: goto l_done;
522: }
523: }
524:
525: l_done:
526: gbuf_freem(m);
527: /*kprintf("at_ioctl: I_done=%d\n", err);*/
528: return err;
529: } /* at_ioctl */
530:
531: int _ATioctl(fp, cmd, arg, proc)
532: void *fp;
533: u_long cmd;
534: register caddr_t arg;
535: void *proc;
536: {
537: int err;
538: gref_t *gref;
539:
540: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) {
541: #ifdef APPLETALK_DEBUG
542: kprintf("_ATioctl: atalk_getref err = %d\n", err);
543: #endif
544: return err;
545: }
546:
547: return((err = at_ioctl(gref, cmd, arg)));
548: }
549:
550: int _ATselect(fp, which, proc)
551: void *fp;
552: int which;
553: void *proc;
554: {
555: int s, err, rc = 0;
556: gref_t *gref;
557:
558: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
559: return err;
560:
561: ATDISABLE(s, gref->lock);
562: if (which == FREAD) {
563: if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
564: rc = 1;
565: else {
566: gref->sevents |= POLLIN;
567: selrecord(proc, &gref->si);
568: }
569: }
570:
571: else if (which == POLLOUT) {
572: if (gref->writeable) {
573: if ((*gref->writeable)(gref))
574: rc = 1;
575: else {
576: gref->sevents |= POLLOUT;
577: selrecord(proc, &gref->si);
578: }
579: } else
580: rc = 1;
581: }
582: ATENABLE(s, gref->lock);
583:
584: return rc;
585: }
586:
587: void atalk_putnext(gref, m)
588: gref_t *gref;
589: gbuf_t *m;
590: {
591: int s;
592:
593: ATDISABLE(s, gref->lock);
594:
595: /* *** potential leak? *** */
596: gbuf_next(m) = 0;
597:
598: switch (gbuf_type(m)) {
599: case MSG_IOCACK:
600: case MSG_IOCNAK:
601: if (gref->ichead)
602: gbuf_next(gref->ichead) = m;
603: else {
604: gref->ichead = m;
605: if (gref->sevents & POLLPRI) {
606: #ifdef APPLETALK_DEBUG
607: kprintf("wakeup gref = 0x%x\n", (unsigned)gref);
608: #endif
609: thread_wakeup(&gref->iocevent);
610: }
611: }
612: break;
613: case MSG_ERROR:
614: /* *** this processing was moved to atalk_notify *** */
615: panic("atalk_putnext receved MSG_ERROR");
616: break;
617: default:
618: if (gref->errno)
619: gbuf_freem(m);
620: else
621: if (gref->rdhead) {
622: gbuf_next(gref->rdtail) = m;
623: gref->rdtail = m;
624: } else {
625: gref->rdhead = m;
626: if (gref->sevents & POLLMSG) {
627: gref->sevents &= ~POLLMSG;
628: thread_wakeup(&gref->event);
629: }
630: if (gref->sevents & POLLIN) {
631: gref->sevents &= ~POLLIN;
632: selwakeup(&gref->si);
633: }
634: gref->rdtail = m;
635: }
636: } /* switch gbuf_type(m) */
637:
638: ATENABLE(s, gref->lock);
639: } /* atalk_putnext */
640:
641: void atalk_enablew(gref)
642: gref_t *gref;
643: {
644: if (gref->sevents & POLLSYNC)
645: thread_wakeup(&gref->event);
646: }
647:
648: void atalk_flush(gref)
649: gref_t *gref;
650: {
651: int s;
652:
653: ATDISABLE(s, gref->lock);
654: if (gref->rdhead) {
655: gbuf_freel(gref->rdhead);
656: gref->rdhead = 0;
657: }
658: if (gref->ichead) {
659: gbuf_freel(gref->ichead);
660: gref->ichead = 0;
661: }
662: ATENABLE(s, gref->lock);
663: }
664:
665: /*
666: * Notify an appletalk user of an asynchronous error;
667: * just wake up so that he can collect error status.
668: */
669: /* *** separate out the error wakeup stuff to eliminate use
670: of MSG_ERROR and atalk_putnext(), moving towards
671: standard socket code
672: *** */
673: void atalk_notify(gref, errno)
674: register gref_t *gref;
675: int errno;
676: {
677: /* *** code from udp_notify() in netinet/udp_usrreq.c
678: inp->inp_socket->so_error = errno;
679: sorwakeup(inp->inp_socket);
680: sowwakeup(inp->inp_socket);
681: *** */
682:
683: int s;
684: ATDISABLE(s, gref->lock);
685:
686: if (gref->errno == 0) {
687: gref->errno = errno;
688: if (gref->rdhead) {
689: gbuf_freel(gref->rdhead);
690: gref->rdhead = 0;
691: }
692: if (gref->sevents & POLLMSG) {
693: gref->sevents &= ~POLLMSG;
694: thread_wakeup(&gref->event);
695: }
696: if (gref->sevents & POLLIN) {
697: gref->sevents &= ~POLLIN;
698: selwakeup(&gref->si);
699: }
700: }
701: ATENABLE(s, gref->lock);
702: } /* atalk_notify */
703:
704: void atalk_notify_sel(gref)
705: gref_t *gref;
706: {
707: int s;
708:
709: ATDISABLE(s, gref->lock);
710: if (gref->sevents & POLLIN) {
711: gref->sevents &= ~POLLIN;
712: selwakeup(&gref->si);
713: }
714: ATENABLE(s, gref->lock);
715: }
716:
717: int atalk_peek(gref, event)
718: gref_t *gref;
719: unsigned char *event;
720: {
721: int s, rc;
722:
723: ATDISABLE(s, gref->lock);
724: if (gref->rdhead) {
725: *event = *gbuf_rptr(gref->rdhead);
726: rc = 0;
727: } else
728: rc = -1;
729: ATENABLE(s, gref->lock);
730:
731: return rc;
732: }
733:
734: static gbuf_t *trace_msg;
735:
736: void atalk_settrace(str, p1, p2, p3, p4, p5)
737: char *str;
738: {
739: int len;
740: gbuf_t *m, *nextm;
741: char trace_buf[256];
742:
743: sprintf(trace_buf, str, p1, p2, p3, p4, p5);
744: len = strlen(trace_buf);
745: #ifdef APPLETALK_DEBUG
746: kprintf("atalk_settrace: gbufalloc size=%d\n", len+1);
747: #endif
748: if ((m = gbuf_alloc(len+1, PRI_MED)) == 0)
749: return;
750: gbuf_wset(m,len);
751: strcpy(gbuf_rptr(m), trace_buf);
752: if (trace_msg) {
753: for (nextm=trace_msg; gbuf_cont(nextm); nextm=gbuf_cont(nextm)) ;
754: gbuf_cont(nextm) = m;
755: } else
756: trace_msg = m;
757: }
758:
759: void atalk_gettrace(m)
760: gbuf_t *m;
761: {
762: if (trace_msg) {
763: gbuf_cont(m) = trace_msg;
764: trace_msg = 0;
765: }
766: }
767:
768: #define GREF_PER_BLK 32
769: static gref_t *gref_free_list = 0;
770:
771: int gref_alloc(grefp)
772: gref_t **grefp;
773: {
774: extern gbuf_t *atp_resource_m;
775: int i, s;
776: gbuf_t *m;
777: gref_t *gref, *gref_array;
778:
779: *grefp = (gref_t *)NULL;
780:
781: ATDISABLE(s, refall_lock);
782: if (gref_free_list == 0) {
783: ATENABLE(s, refall_lock);
784: #ifdef APPLETALK_DEBUG
785: kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t));
786: #endif
787: if ((m = gbuf_alloc(GREF_PER_BLK*sizeof(gref_t),PRI_HI)) == 0)
788: return ENOBUFS;
789: bzero(gbuf_rptr(m), GREF_PER_BLK*sizeof(gref_t));
790: gref_array = (gref_t *)gbuf_rptr(m);
791: for (i=0; i < GREF_PER_BLK-1; i++)
792: gref_array[i].atpcb_next = (gref_t *)&gref_array[i+1];
793: ATDISABLE(s, refall_lock);
794: gbuf_cont(m) = atp_resource_m;
795: atp_resource_m = m;
796: gref_array[i].atpcb_next = gref_free_list;
797: gref_free_list = (gref_t *)&gref_array[0];
798: }
799:
800: gref = gref_free_list;
801: gref_free_list = gref->atpcb_next;
802: ATENABLE(s, refall_lock);
803: ATLOCKINIT(gref->lock);
804: //### LD Test 08/05/98
805: // simple_lock_init(&gref->lock);
806: ATEVENTINIT(gref->event);
807: ATEVENTINIT(gref->iocevent);
808:
809: /* *** just for now *** */
810: gref->atpcb_socket = (struct socket *)NULL;
811:
812: *grefp = gref;
813: return 0;
814: } /* gref_alloc */
815:
816: static int gref_close(gref)
817: gref_t *gref;
818: {
819: int s, rc;
820:
821: switch (gref->proto) {
822:
823: /* ATPROTO_DDP and ATPROTO_LAP have been replaced with
824: BSD-style socket interface. */
825:
826: case ATPROTO_ATP:
827: rc = atp_close(gref, 1); break;
828: case ATPROTO_ASP:
829: rc = asp_close(gref); break;
830: #ifdef AURP_SUPPORT
831: case ATPROTO_AURP:
832: rc = aurp_close(gref); break;
833: break;
834: #endif
835: case ATPROTO_ADSP:
836: rc = adsp_close(gref); break;
837: default:
838: rc = 0;
839: break;
840: }
841:
842: if (rc == 0) {
843: atalk_flush(gref);
844: selthreadclear(&gref->si);
845:
846: /* from original gref_free() */
847: ATDISABLE(s, refall_lock);
848: bzero((char *)gref, sizeof(gref_t));
849: gref->atpcb_next = gref_free_list;
850: gref_free_list = gref;
851: ATENABLE(s, refall_lock);
852: }
853:
854: return rc;
855: }
856:
857: /*
858: Buffer Routines
859:
860: *** Some to be replaced with mbuf routines, some to be re-written
861: as mbuf routines (and moved to kern/uicp_mbuf.c or sys/mbuf.h?).
862: ***
863:
864: */
865:
866: /*
867: * LD 5/12/97 Added for MacOSX, defines a m_clattach function that:
868: * "Allocates an mbuf structure and attaches an external cluster."
869: */
870:
871: struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait)
872: caddr_t extbuf;
873: int (*extfree)();
874: int extsize;
875: int extarg;
876: int wait;
877: {
878: struct mbuf *m;
879:
880: if ((m = m_gethdr(wait, MSG_DATA)) == NULL)
881: return (NULL);
882:
883: m->m_ext.ext_buf = extbuf;
884: m->m_ext.ext_free = extfree;
885: m->m_ext.ext_size = extsize;
886: m->m_ext.ext_arg = extarg;
887: m->m_ext.ext_refs.forward =
888: m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
889: m->m_data = extbuf;
890: m->m_flags |= M_EXT;
891:
892: return (m);
893: }
894:
895: /*
896: Used as the "free" routine for over-size clusters allocated using
897: m_lgbuf_alloc().
898: */
899:
900: void m_lgbuf_free(buf, size, arg)
901: void *buf;
902: int size, arg; /* not needed, but they're in m_free() */
903: {
904: FREE(buf, M_MCLUST);
905: }
906:
907: /*
908: Used to allocate an mbuf when there is the possibility that it may
909: need to be larger than the size of a standard cluster.
910: */
911:
912: struct mbuf *m_lgbuf_alloc(size, wait)
913: int size, wait;
914: {
915: struct mbuf *m;
916:
917: /* If size is too large, allocate a cluster, otherwise, use the
918: standard mbuf allocation routines.*/
919: if (size > MCLBYTES) {
920: void *buf;
921: if (NULL ==
922: (buf = (void *)_MALLOC(size, M_MCLUST,
923: (wait)? M_WAITOK: M_NOWAIT))) {
924: return(NULL);
925: }
926: if (NULL ==
927: (m = m_clattach(buf, m_lgbuf_free, size, 0,
928: (wait)? M_WAIT: M_DONTWAIT))) {
929: m_lgbuf_free(buf);
930: return(NULL);
931: }
932: } else {
933: m = m_gethdr(((wait)? M_WAIT: M_DONTWAIT), MSG_DATA);
934: if (m && (size > MHLEN)) {
935: MCLGET(m, ((wait)? M_WAIT: M_DONTWAIT));
936: if (!(m->m_flags & M_EXT)) {
937: (void)m_free(m);
938: return(NULL);
939: }
940: }
941: }
942:
943: return(m);
944: } /* m_lgbuf_alloc */
945:
946: /*
947: gbuf_alloc() is a wrapper for m_lgbuf_alloc(), which is used to
948: allocate an mbuf when there is the possibility that it may need
949: to be larger than the size of a standard cluster.
950:
951: gbuf_alloc() sets the mbuf lengths, unlike the standard mbuf routines.
952: */
953:
954: gbuf_t *gbuf_alloc_wait(size, wait)
955: int size, wait;
956: {
957: gbuf_t *m = (gbuf_t *)m_lgbuf_alloc(size, wait);
958:
959: /* Standard mbuf allocation routines assume that the caller
960: will set the size. */
961: if (m) {
962: (struct mbuf *)m->m_pkthdr.len = size;
963: (struct mbuf *)m->m_len = size;
964: }
965:
966: return(m);
967: }
968:
969: int gbuf_msgsize(m)
970: gbuf_t *m;
971: {
972: int size;
973:
974: for (size=0; m; m=gbuf_cont(m))
975: size += gbuf_len(m);
976: return size;
977: }
978:
979: int append_copy(m1, m2, wait)
980: struct mbuf *m1, *m2;
981: int wait;
982: {
983: if ((!(m1->m_flags & M_EXT)) && (!(m2->m_flags & M_EXT)) &&
984: (m_trailingspace(m1) >= m2->m_len)) {
985: /* splat the data from one into the other */
986: bcopy(mtod(m2, caddr_t), mtod(m1, caddr_t) + m1->m_len,
987: (u_int)m2->m_len);
988: m1->m_len += m2->m_len;
989: if (m1->m_flags & M_PKTHDR)
990: m1->m_pkthdr.len += m2->m_len;
991: return 1;
992: }
993: if ((m1->m_next = m_copym(m2, 0, m2->m_len,
994: (wait)? M_WAIT: M_DONTWAIT)) == NULL)
995: return 0;
996: return 1;
997: } /* append_copy */
998:
999: /*
1000: Copy an mbuf chain, referencing existing external storage, if any.
1001: Leave space for a header in the new chain, if the space has been
1002: left in the origin chain.
1003: */
1004: struct mbuf *copy_pkt(mlist, pad)
1005: struct mbuf *mlist; /* the mbuf chain to be copied */
1006: int pad; /* hint as to how long the header might be
1007: If pad is < 0, leave the same amount of space
1008: as there was in the original. */
1009: {
1010: struct mbuf *new_m;
1011: int len;
1012:
1013: if (pad < 0)
1014: len = m_leadingspace(mlist);
1015: else
1016: len = min(pad, m_leadingspace(mlist));
1017:
1018: /* preserve space for the header at the beginning of the mbuf */
1019: if (len) {
1020: mlist->m_data -= (len);
1021: mlist->m_len += (len);
1022: if (mlist->m_flags & M_PKTHDR)
1023: mlist->m_pkthdr.len += (len);
1024: new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT);
1025: m_adj(mlist, len);
1026: m_adj(new_m, len);
1027: } else
1028: new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT);
1029:
1030: return(new_m);
1031: }
1032:
1033: void gbuf_linkb(m1, m2)
1034: gbuf_t *m1;
1035: gbuf_t *m2;
1036: {
1037: while (gbuf_cont(m1) != 0)
1038: m1 = gbuf_cont(m1);
1039: gbuf_cont(m1) = m2;
1040: }
1041:
1042: void gbuf_linkpkt(m1, m2)
1043: gbuf_t *m1;
1044: gbuf_t *m2;
1045: {
1046: while (gbuf_next(m1) != 0)
1047: m1 = gbuf_next(m1);
1048: gbuf_next(m1) = m2;
1049: }
1050:
1051: int gbuf_freel(m)
1052: gbuf_t *m;
1053: {
1054: gbuf_t *tmp_m;
1055:
1056: while ((tmp_m = m) != 0) {
1057: m = gbuf_next(m);
1058: gbuf_next(tmp_m) = 0;
1059: gbuf_freem(tmp_m);
1060: }
1061: return (0);
1062: }
1063:
1064: /* free empty mbufs at the front of the chain */
1065: gbuf_t *gbuf_strip(m)
1066: gbuf_t *m;
1067: {
1068: gbuf_t *tmp_m;
1069:
1070: while (m && gbuf_len(m) == 0) {
1071: tmp_m = m;
1072: m = gbuf_cont(m);
1073: gbuf_freeb(tmp_m);
1074: }
1075: return(m);
1076: }
1077:
1078: /**************************************/
1079:
1080: int ddp_adjmsg(m, len)
1081: gbuf_t *m;
1082: int len;
1083: {
1084: int buf_len;
1085: gbuf_t *curr_m, *prev_m;
1086:
1087: if (m == (gbuf_t *)0)
1088: return 0;
1089:
1090: if (len > 0) {
1091: for (curr_m=m; curr_m;) {
1092: buf_len = gbuf_len(curr_m);
1093: if (len < buf_len) {
1094: gbuf_rinc(curr_m,len);
1095: return 1;
1096: }
1097: len -= buf_len;
1098: gbuf_rinc(curr_m,buf_len);
1099: if ((curr_m = gbuf_cont(curr_m)) == 0) {
1100: gbuf_freem(m);
1101: return 0;
1102: }
1103: }
1104:
1105: } else if (len < 0) {
1106: len = -len;
1107: l_cont: prev_m = 0;
1108: for (curr_m=m; gbuf_cont(curr_m);
1109: prev_m=curr_m, curr_m=gbuf_cont(curr_m)) ;
1110: buf_len = gbuf_len(curr_m);
1111: if (len < buf_len) {
1112: gbuf_wdec(curr_m,len);
1113: return 1;
1114: }
1115: if (prev_m == 0)
1116: return 0;
1117: gbuf_cont(prev_m) = 0;
1118: gbuf_freeb(curr_m);
1119: len -= buf_len;
1120: goto l_cont;
1121:
1122: } else
1123: return 1;
1124: }
1125:
1126: /*
1127: * The message chain, m is grown in size by len contiguous bytes.
1128: * If len is non-negative, len bytes are added to the
1129: * end of the gbuf_t chain. If len is negative, the
1130: * bytes are added to the front. ddp_growmsg only adds bytes to
1131: * message blocks of the same type.
1132: * It returns a pointer to the new gbuf_t on sucess, 0 on failure.
1133: */
1134:
1135: gbuf_t *ddp_growmsg(mp, len)
1136: gbuf_t *mp;
1137: int len;
1138: {
1139: gbuf_t *m, *d;
1140:
1141: if ((m = mp) == (gbuf_t *) 0)
1142: return ((gbuf_t *) 0);
1143:
1144: if (len <= 0) {
1145: len = -len;
1146: if ((d = gbuf_alloc(len, PRI_MED)) == 0)
1147: return ((gbuf_t *) 0);
1148: gbuf_set_type(d, gbuf_type(m));
1149: gbuf_wset(d,len);
1150: /* link in new gbuf_t */
1151: gbuf_cont(d) = m;
1152: return (d);
1153:
1154: } else {
1155: register int count;
1156: /*
1157: * Add to tail.
1158: */
1159: if ((count = gbuf_msgsize(m)) < 0)
1160: return ((gbuf_t *) 0);
1161: /* find end of chain */
1162: for ( ; m; m = gbuf_cont(m)) {
1163: if (gbuf_len(m) >= count)
1164: break;
1165: count -= gbuf_len(m);
1166: }
1167: /* m now points to gbuf_t to add to */
1168: if ((d = gbuf_alloc(len, PRI_MED)) == 0)
1169: return ((gbuf_t *) 0);
1170: gbuf_set_type(d, gbuf_type(m));
1171: /* link in new gbuf_t */
1172: gbuf_cont(d) = gbuf_cont(m);
1173: gbuf_cont(m) = d;
1174: gbuf_wset(d,len);
1175: return (d);
1176: }
1177: }
1178:
1179: /*
1180: * return the MSG_IOCACK/MSG_IOCNAK. Note that the same message
1181: * block is used as the vehicle, and that if there is an error return,
1182: * then linked blocks are lopped off. BEWARE of multiple references.
1183: * Used by other appletalk modules, so it is not static!
1184: */
1185:
1186: void ioc_ack(errno, m, gref)
1187: int errno;
1188: register gbuf_t *m;
1189: register gref_t *gref;
1190: {
1191: ioc_t *iocbp = (ioc_t *)gbuf_rptr(m);
1192:
1193: /*kprintf("ioc_ack: m=%x gref=%x errno=%d\n", m, gref, errno);*/
1194: if ((iocbp->ioc_error = errno) != 0)
1195: { /* errno != 0, then there is an error, get rid of linked blocks! */
1196:
1197: if (gbuf_cont(m)) {
1198: gbuf_freem(gbuf_cont(m));
1199: gbuf_cont(m) = 0;
1200: }
1201: gbuf_set_type(m, MSG_IOCNAK);
1202: iocbp->ioc_count = 0; /* only make zero length if error */
1203: iocbp->ioc_rval = -1;
1204: } else
1205: gbuf_set_type(m, MSG_IOCACK);
1206:
1207: atalk_putnext(gref, m);
1208: }
1209:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.