|
|
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-1998 Apple Computer, Inc.
24: * All Rights Reserved.
25: */
26:
27: /*
28: * 09/07/95 - Modified for performance (Tuyen Nguyen)
29: * Modified for MP, 1996 by Tuyen Nguyen
30: * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
31: */
32: #include <sys/errno.h>
33: #include <sys/types.h>
34: #include <sys/param.h>
35: #include <machine/spl.h>
36: #include <sys/systm.h>
37: #include <sys/kernel.h>
38: #include <sys/proc.h>
39: #include <sys/filedesc.h>
40: #include <sys/fcntl.h>
41: #include <sys/mbuf.h>
42: #include <sys/socket.h>
43: #include <sys/socketvar.h>
44: #include <sys/time.h>
45: #include <sys/ioctl.h>
46: #include <sys/malloc.h>
47:
48: #include <net/if.h>
49:
50: #include <netat/sysglue.h>
51: #include <netat/appletalk.h>
52: #include <netat/ddp.h>
53: #include <netat/at_snmp.h>
54: #include <netat/at_pcb.h>
55: #include <netat/debug.h>
56: #include <netat/at_var.h>
57: #include <netat/adsp.h>
58: #include <netat/adsp_internal.h>
59:
60: void SndMsgUp();
61: void adsp_rput();
62: static void adsp_iocack();
63: static void adsp_iocnak();
64: void adsp_dequeue_ccb();
65: unsigned char adspAssignSocket();
66: int adspallocate(), adsprelease();
67: int adspInited = 0;
68:
69: atlock_t adspall_lock;
70: atlock_t adspgen_lock;
71: GLOBAL adspGlobal;
72:
73: /**********/
74:
75: int adsp_pidM[256];
76: char adsp_inputC[256];
77: CCB *adsp_inputQ[256];
78:
79: extern char ot_adsp_socketM[];
80: extern at_ifaddr_t *ifID_home;
81:
82: CCB *ccb_used_list;
83:
84: void adsp_input(mp)
85: gbuf_t *mp;
86: {
87: gref_t *gref;
88: CCBPtr sp;
89: at_ddp_t *p;
90: int s, l;
91: gbuf_t *mb;
92:
93: switch (gbuf_type(mp)) {
94: case MSG_DATA:
95: p = (at_ddp_t *)gbuf_rptr(mp);
96: ATDISABLE(s, adspall_lock);
97: sp = adsp_inputQ[p->dst_socket];
98: if ((sp == 0) || (sp->gref==0) || (sp->state==sClosed))
99: {
100: ATENABLE(s, adspall_lock);
101: gbuf_freem(mp);
102: return;
103: }
104: else if (sp->otccbLink != 0) {
105: do {
106: if ((sp->remoteAddress.a.node == p->src_node)
107: && (sp->remoteAddress.a.socket == p->src_socket)
108: && (sp->remoteAddress.a.net == NET_VALUE(p->src_net)))
109: break;
110: } while ((sp = sp->otccbLink) != 0);
111: if (sp == 0)
112: {
113: ATENABLE(s, adspall_lock);
114: gbuf_freem(mp);
115: return;
116: }
117: }
118: if (sp->lockFlag) {
119: gbuf_next(mp) = 0;
120: if (sp->deferred_mb) {
121: for (mb=sp->deferred_mb; gbuf_next(mb); mb=gbuf_next(mb)) ;
122: gbuf_next(mb) = mp;
123: } else
124: sp->deferred_mb = mp;
125: ATENABLE(s, adspall_lock);
126: return;
127: }
128: ATDISABLE(l, sp->lockRemove);
129: sp->lockFlag = 1;
130: ATENABLE(l, adspall_lock);
131: while (mp) {
132: adsp_rput(sp->gref, mp);
133: if ((mp = sp->deferred_mb) != 0) {
134: sp->deferred_mb = gbuf_next(mp);
135: gbuf_next(mp) = 0;
136: }
137: }
138: sp->lockFlag = 0;
139: ATENABLE(s, sp->lockRemove);
140: return;
141:
142: case MSG_IOCACK:
143: case MSG_IOCNAK:
144: gref = (gref_t *)((ioc_t *)gbuf_rptr(mp))->ioc_private;
145: break;
146:
147: case MSG_IOCTL:
148: #ifdef APPLETALK_DEBUG
149: kprintf("unexpected MSG_IOCTL in adsp_input()");
150: #endif
151: /* fall through */
152:
153: default:
154: gbuf_freem(mp);
155: return;
156: }
157:
158: adsp_rput(gref, mp);
159: }
160:
161: /**********/
162: int adsp_readable(gref)
163: gref_t *gref;
164: {
165: int rc;
166: CCBPtr sp;
167:
168: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
169: rc = sp->rData;
170:
171: return rc;
172: }
173:
174: int adsp_writeable(gref)
175: gref_t *gref;
176: {
177: int s, rc;
178: CCBPtr sp;
179:
180: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
181: ATDISABLE(s, sp->lock);
182: rc = CalcSendQFree(sp);
183: ATENABLE(s, sp->lock);
184:
185: return rc;
186: }
187:
188: static void adsp_init()
189: {
190: adspInited++;
191: InitGlobals();
192: ccb_used_list = 0;
193: bzero(adsp_pidM, sizeof(adsp_pidM));
194: bzero(adsp_inputC, sizeof(adsp_inputC));
195: bzero(adsp_inputQ, sizeof(adsp_inputQ));
196: }
197:
198: /*
199: * Description:
200: * ADSP open and close routines. These routines
201: * initalize and release the ADSP structures. They do not
202: * have anything to do with "connections"
203: */
204:
205: int adsp_open(gref)
206: gref_t *gref;
207: {
208: register CCBPtr sp;
209: int s;
210:
211: if (!adspInited)
212: adsp_init();
213:
214: if (!adspAllocateCCB(gref))
215: return(ENOBUFS); /* can't get buffers */
216:
217: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
218: gref->readable = adsp_readable;
219: gref->writeable = adsp_writeable;
220: ATDISABLE(s, adspall_lock);
221: if ((sp->otccbLink = ccb_used_list) != 0)
222: sp->otccbLink->ccbLink = sp;
223: ccb_used_list = sp;
224: ATENABLE(s, adspall_lock);
225: return 0;
226: }
227:
228: int adsp_close(gref)
229: gref_t *gref;
230: {
231: int s, l;
232: unsigned char localSocket;
233:
234: /* make sure we've not yet removed the CCB (e.g., due to TrashSession) */
235: ATDISABLE(l, adspgen_lock);
236: if (gref->info) {
237: CCBPtr sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
238: ATDISABLE(s, sp->lock);
239: ATENABLE(s, adspgen_lock);
240: localSocket = sp->localSocket;
241: ATENABLE(l, sp->lock);
242: if (localSocket)
243: adspRelease(gref);
244: else
245: {
246: adsp_dequeue_ccb(sp);
247: gbuf_freeb((gbuf_t *)gref->info);
248: }
249: } else
250: ATENABLE(l, adspgen_lock);
251: return 0;
252: }
253:
254:
255: /*
256: * Name:
257: * adsp_rput
258: *
259: * Description:
260: * ADSP streams read put and service routines.
261: */
262:
263: void adsp_rput(gref, mp)
264: gref_t *gref; /* READ queue */
265: gbuf_t *mp;
266: {
267: switch (gbuf_type(mp)) {
268: case MSG_HANGUP:
269: case MSG_IOCACK:
270: case MSG_IOCNAK:
271: switch (adspReadHandler(gref, mp)) {
272: case STR_PUTNEXT:
273: atalk_putnext(gref, mp);
274: break;
275: case STR_IGNORE:
276: break;
277: }
278: break;
279: case MSG_ERROR:
280: #ifdef APPLETALK_DEBUG
281: kprintf("adsp_rput received MSG_ERROR");
282: #endif
283: /* fall through */
284: default:
285: CheckReadQueue(gbuf_rptr(((gbuf_t *)gref->info)));
286: CheckSend(gbuf_rptr(((gbuf_t *)gref->info)));
287:
288: switch (gbuf_type(mp)) {
289: case MSG_IOCTL:
290: case MSG_DATA:
291: case MSG_PROTO:
292: if (adspReadHandler(gref, mp) == STR_PUTNEXT)
293: atalk_putnext(gref, mp);
294: break;
295: default:
296: atalk_putnext(gref, mp);
297: break;
298: }
299: }
300: }
301:
302: /*
303: * Name:
304: * adsp_wput
305: *
306: * Description:
307: * ADSP streams write put and service routines.
308: *
309: */
310:
311: int adsp_wput(gref, mp)
312: gref_t *gref; /* WRITE queue */
313: gbuf_t *mp;
314: {
315: int rc;
316: int s;
317: gbuf_t *xm;
318: ioc_t *iocbp;
319: CCBPtr sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
320:
321: if (gbuf_type(mp) == MSG_IOCTL) {
322: iocbp = (ioc_t *)gbuf_rptr(mp);
323: switch (iocbp->ioc_cmd) {
324: case ADSPBINDREQ:
325: {
326: unsigned char v;
327:
328: if (gbuf_cont(mp) == NULL) {
329: iocbp->ioc_rval = -1;
330: adsp_iocnak(gref, mp, EINVAL);
331: }
332: v = *(unsigned char *)gbuf_rptr(gbuf_cont(mp));
333: ATDISABLE(s, adspall_lock);
334: if ( (v != 0)
335: && ((v > DDP_SOCKET_LAST) || (v < 2)
336: || (adsp_inputQ[v] != 0)
337: || (ot_adsp_socketM[v] != 0)) ) {
338: ATENABLE(s, adspall_lock);
339: iocbp->ioc_rval = -1;
340: adsp_iocnak(gref, mp, EINVAL);
341: }
342: else {
343: if (v == 0) {
344: ATENABLE(s, adspall_lock);
345: if ((v = adspAssignSocket(gref, 0)) == 0) {
346: iocbp->ioc_rval = -1;
347: adsp_iocnak(gref, mp, EINVAL);
348: return 0;
349: }
350: } else {
351: adsp_inputC[v] = 1;
352: adsp_inputQ[v] = sp;
353: adsp_pidM[v] = sp->pid;
354: ATENABLE(s, adspall_lock);
355: adsp_dequeue_ccb(sp);
356: }
357: *(unsigned char *)gbuf_rptr(gbuf_cont(mp)) = v;
358: sp->localSocket = v;
359: iocbp->ioc_rval = 0;
360: adsp_iocack(gref, mp);
361: }
362: return 0;
363: }
364:
365: case ADSPGETSOCK:
366: case ADSPGETPEER:
367: {
368: at_inet_t *addr;
369:
370: if (((xm = gbuf_cont(mp)) == NULL)
371: && ((xm = gbuf_alloc(sizeof(at_inet_t), PRI_MED)) == NULL)) {
372: iocbp->ioc_rval = -1;
373: adsp_iocnak(gref, mp, ENOBUFS);
374: return 0;
375: }
376: gbuf_cont(mp) = xm;
377: gbuf_wset(xm,sizeof(at_inet_t));
378: addr = (at_inet_t *)gbuf_rptr(xm);
379: if (iocbp->ioc_cmd == ADSPGETSOCK) {
380: /* Obtain Network and Node Id's from DDP */
381: /* *** was ddp_get_cfg() *** */
382: addr->net = ifID_home->ifThisNode.s_net;
383: addr->node = ifID_home->ifThisNode.s_node;
384: addr->socket = (sp)? sp->localSocket: 0;
385: } else
386: if (sp)
387: *addr = sp->remoteAddress.a;
388: else {
389: addr->net = 0;
390: addr->node = 0;
391: addr->socket = 0;
392: }
393: iocbp->ioc_rval = 0;
394: adsp_iocack(gref, mp);
395: return 0;
396: }
397: case DDP_IOC_GET_CFG:
398: /* respond to an DDP_IOC_GET_CFG sent on an adsp fd */
399: if (((xm = gbuf_cont(mp)) == NULL) &&
400: (xm = gbuf_alloc(sizeof(at_inet_t), PRI_MED)) == NULL) {
401: iocbp->ioc_rval = -1;
402: adsp_iocnak(gref, mp, ENOBUFS);
403: return 0;
404: }
405: gbuf_cont(mp) = xm;
406: gbuf_wset(xm, sizeof(ddp_addr_t));
407: /* Obtain Network and Node Id's from DDP */
408: {
409: /* *** was ddp_get_cfg() *** */
410: ddp_addr_t *cfgp =
411: (ddp_addr_t *)gbuf_rptr(gbuf_cont(mp));
412: cfgp->inet.net = ifID_home->ifThisNode.s_net;
413: cfgp->inet.node = ifID_home->ifThisNode.s_node;
414: cfgp->inet.socket = (sp)? sp->localSocket: 0;
415: cfgp->ddptype = DDP_ADSP;
416: }
417: iocbp->ioc_rval = 0;
418: adsp_iocack(gref, mp);
419: return 0;
420: } /* switch */
421: }
422:
423: if (!gref->info)
424: gbuf_freem(mp);
425: else {
426: ATDISABLE(s, sp->lockClose);
427: rc = adspWriteHandler(gref, mp);
428: ATENABLE(s, sp->lockClose);
429:
430: switch (rc) {
431: case STR_PUTNEXT:
432: if (gbuf_type(mp) == MSG_IOCTL) {
433: iocbp = (ioc_t *)gbuf_rptr(mp);
434: iocbp->ioc_private = (void *)gref;
435: }
436: DDP_OUTPUT(mp);
437: break;
438: case STR_IGNORE:
439: case STR_IGNORE+99:
440: break;
441: default:
442: gbuf_freem(mp);
443: break;
444: }
445: }
446:
447: return 0;
448: } /* adsp_wput */
449:
450: void adspioc_ack(errno, m, gref)
451: int errno;
452: gbuf_t *m;
453: gref_t *gref;
454: {
455: ioc_t *iocbp;
456:
457: if (m == NULL)
458: return;
459: iocbp = (ioc_t *) gbuf_rptr(m);
460:
461: iocbp->ioc_error = errno; /* set the errno */
462: iocbp->ioc_count = gbuf_msgsize(gbuf_cont(m));
463: if (gbuf_type(m) == MSG_IOCTL) /* if an ioctl, this is an ack */
464: gbuf_set_type(m, MSG_IOCACK); /* and ALWAYS update the user */
465: /* ioctl structure */
466: trace_mbufs(D_M_ADSP,"A ", m);
467: SndMsgUp(gref, m);
468: }
469:
470: static void adsp_iocack(gref, m)
471: gref_t *gref;
472: register gbuf_t *m;
473: {
474: if (gbuf_type(m) == MSG_IOCTL)
475: gbuf_set_type(m, MSG_IOCACK);
476:
477: if (gbuf_cont(m))
478: ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(gbuf_cont(m));
479: else
480: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
481:
482: SndMsgUp(gref, m);
483: }
484:
485:
486: static void adsp_iocnak(gref, m, err)
487: gref_t *gref;
488: register gbuf_t *m;
489: register int err;
490: {
491: if (gbuf_type(m) == MSG_IOCTL)
492: gbuf_set_type(m, MSG_IOCNAK);
493: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
494:
495: if (err == 0)
496: err = ENXIO;
497: ((ioc_t *)gbuf_rptr(m))->ioc_error = err;
498:
499: if (gbuf_cont(m)) {
500: gbuf_freem(gbuf_cont(m));
501: gbuf_cont(m) = NULL;
502: }
503: SndMsgUp(gref, m);
504: }
505:
506: unsigned char
507: adspAssignSocket(gref, flag)
508: gref_t *gref;
509: int flag;
510: {
511: unsigned char sVal, sMax, sMin, sSav, inputC;
512: CCBPtr sp;
513: int s;
514:
515: sMax = flag ? DDP_SOCKET_LAST-46 : DDP_SOCKET_LAST-6;
516: sMin = DDP_SOCKET_1st_DYNAMIC-64;
517:
518: ATDISABLE(s, adspall_lock);
519: for (inputC=255, sVal=sMax; sVal >= sMin; sVal--) {
520: if (!ot_adsp_socketM[sVal]) {
521: if (!adsp_inputQ[sVal])
522: break;
523: else if (flag) {
524: if ((adsp_inputC[sVal] < inputC)
525: && (adsp_inputQ[sVal]->state == sOpen)) {
526: inputC = adsp_inputC[sVal];
527: sSav = sVal;
528: }
529: }
530: }
531: }
532:
533: if (sVal < sMin) {
534: if (!flag || (inputC == 255)) {
535: ATENABLE(s, adspall_lock);
536: return 0;
537: }
538: sVal = sSav;
539: }
540: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
541: ATENABLE(s, adspall_lock);
542: adsp_dequeue_ccb(sp);
543: ATDISABLE(s, adspall_lock);
544: adsp_inputC[sVal]++;
545: sp->otccbLink = adsp_inputQ[sVal];
546: adsp_inputQ[sVal] = sp;
547: if (!flag)
548: adsp_pidM[sVal] = sp->pid;
549: ATENABLE(s, adspall_lock);
550: return sVal;
551: }
552:
553: int
554: adspDeassignSocket(sp)
555: CCBPtr sp;
556: {
557: unsigned char sVal;
558: CCBPtr curr_sp;
559: CCBPtr prev_sp;
560: int pid = 0;
561: int s, l;
562:
563: dPrintf(D_M_ADSP, D_L_TRACE, ("adspDeassignSocket: pid=%d,s=%d\n",
564: sp->pid, sp->localSocket));
565: ATDISABLE(s, adspall_lock);
566: sVal = sp->localSocket;
567: if ((curr_sp = adsp_inputQ[sVal]) != 0) {
568: prev_sp = 0;
569: while (curr_sp != sp) {
570: prev_sp = curr_sp;
571: curr_sp = curr_sp->otccbLink;
572: }
573: if (curr_sp) {
574: ATDISABLE(l, sp->lockRemove);
575: if (prev_sp)
576: prev_sp->otccbLink = sp->otccbLink;
577: else
578: adsp_inputQ[sVal] = sp->otccbLink;
579: ATENABLE(l, sp->lockRemove);
580: if (adsp_inputQ[sVal])
581: adsp_inputC[sVal]--;
582: else {
583: pid = adsp_pidM[sVal];
584: adsp_inputC[sVal] = 0;
585: adsp_pidM[sVal] = 0;
586: }
587: sp->ccbLink = 0;
588: sp->otccbLink = 0;
589: sp->localSocket = 0;
590: ATENABLE(s, adspall_lock);
591: return pid ? 0 : 1;
592: }
593: }
594: ATENABLE(s, adspall_lock);
595:
596: dPrintf(D_M_ADSP, D_L_ERROR,
597: ("adspDeassignSocket: closing, no CCB block, trouble ahead\n"));
598: return -1;
599: } /* adspDeassignSocket */
600:
601: /*
602: * remove CCB from the use list
603: */
604: void
605: adsp_dequeue_ccb(sp)
606: CCB *sp;
607: {
608: int s;
609:
610: ATDISABLE(s, adspall_lock);
611: if (sp == ccb_used_list) {
612: if ((ccb_used_list = sp->otccbLink) != 0)
613: sp->otccbLink->ccbLink = 0;
614: } else if (sp->ccbLink) {
615: if ((sp->ccbLink->otccbLink = sp->otccbLink) != 0)
616: sp->otccbLink->ccbLink = sp->ccbLink;
617: }
618:
619: sp->otccbLink = 0;
620: sp->ccbLink = 0;
621: ATENABLE(s, adspall_lock);
622: }
623:
624: void SndMsgUp(gref, mp)
625: gref_t *gref; /* WRITE queue */
626: gbuf_t *mp;
627: {
628: /*
629: dPrintf(D_M_ADSP, D_L_TRACE,
630: ("SndMsgUp: gref=0x%x, mbuf=0x%x\n", (unsigned)gref, (unsigned)mp));
631: trace_mbufs(D_M_ADSP, " m", mp);
632: */
633: atalk_putnext(gref, mp);
634: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.