|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1988, 1989, 1997, 1998 Apple Computer, Inc.
27: *
28: * The information contained herein is subject to change without
29: * notice and should not be construed as a commitment by Apple
30: * Computer, Inc. Apple Computer, Inc. assumes no responsibility
31: * for any errors that may appear.
32: *
33: * Confidential and Proprietary to Apple Computer, Inc.
34: */
35:
36: /* ddp_proto.c: 2.0, 1.23; 10/18/93; Apple Computer, Inc. */
37:
38: #include <sysglue.h>
39: #ifdef _AIX
40: #include <sys/sysmacros.h>
41: #endif
42: #include <sys/buf.h>
43: #include <at/appletalk.h>
44: #include <atlog.h>
45: #include <lap.h>
46: #include <at/ddp.h>
47: #include <at/zip.h>
48: #include <at/at_lap.h>
49: #include <at_ddp.h>
50: #include <at/elap.h>
51: #include <h/at_elap.h>
52:
53: extern atlock_t ddpall_lock;
54: extern atlock_t ddpinp_lock;
55: extern int ot_protoCnt;
56:
57: #define DDPCLONEMIN 1
58:
59: /* Pointer to LAP interface which DDP addresses are tied to */
60: extern at_if_t *ifID_table[];
61:
62: ddp_dev_t ddp_devs[DDP_SOCKET_LAST+1];
63:
64: static void ddp_stop_ack();
65: char ddp_off_flag;
66: static gbuf_t *ddp_ack_m;
67: static gref_t *ddp_ack_gref;
68:
69: int
70: lap_open(gref)
71: gref_t *gref;
72: {
73: int rc;
74:
75: if ((rc = ddp_open(gref)) == 0)
76: ((ddp_dev_t *)gref->info)->pid = 0;
77: return rc;
78: }
79:
80: int
81: ddp_open(gref)
82: gref_t *gref;
83: {
84: int s;
85: int i;
86:
87: if ((ot_protoCnt >= 3) && !ifID_table[IFID_HOME]) {
88: return(ENETDOWN);
89: }
90:
91: /*
92: * If not ready, return error
93: */
94: if (ddp_off_flag)
95: return ENOTREADY;
96:
97: /* Look for an unused minor number */
98: ATDISABLE(s, ddpall_lock);
99: for (i=DDPCLONEMIN; i <= DDP_SOCKET_LAST; i++) {
100: if (!ddp_devs[i].flags) {
101: break; /* Either ALLOCATED or SHUTDOWN */
102: }
103: }
104:
105: if (i > DDP_SOCKET_LAST) {
106: ATENABLE(s, ddpall_lock);
107: return(EADDRNOTAVAIL);
108: }
109:
110: /* If we arrive here, i is the minor number to be
111: * allocated for this stream.
112: */
113: ddp_devs[i].flags |= DDPF_ALLOCATED;
114: ddp_devs[i].proto = 0;
115: ddp_devs[i].sock_entry = NULL;
116: ddp_devs[i].pid = gref->pid;
117: gref->info = (void *)&ddp_devs[i];
118: ATENABLE(s, ddpall_lock);
119:
120: return(0);
121: }
122:
123: int
124: ddp_close(gref)
125: gref_t *gref;
126: {
127: int s;
128: int rc = 0;
129:
130: /*
131: * Free the entry for this queue in the ddp_devs table.
132: * Can clear both DDPF_ALLOCATED, DDPF_SHUTDOWN since this is the
133: * "last close" for this device.
134: */
135: ATDISABLE(s, ddpall_lock);
136: ((ddp_dev_t *)gref->info)->flags = 0;
137:
138: /* protect against the case where close is done on socket that's
139: * not bound
140: */
141: if (DDP_SOCKENTRY(gref))
142: rc = ddp_close_socket(DDP_SOCKENTRY(gref));
143: ATENABLE(s, ddpall_lock);
144: return rc;
145: }
146:
147: int ddp_putmsg(gref, mp)
148: gref_t *gref;
149: gbuf_t *mp;
150: {
151: extern char ot_protoT[];
152: ddp_socket_t socket;
153: register ioc_t *iocbp;
154: register int error;
155: at_ddp_t *ddp;
156: at_inet_t *addr;
157: gbuf_t *ymp;
158: union at_ddpopt *ddpopt;
159:
160: switch(gbuf_type(mp)) {
161: case MSG_DATA :
162: /* If this message is going out on a socket that's not bound,
163: * nail it.
164: */
165: ddp = (at_ddp_t *)gbuf_rptr(mp);
166: if (ot_protoT[ddp->type]) {
167: if ((gref == 0) || !DDP_SOCKENTRY(gref)) {
168: int src_addr_included = ((ddp->type==3) && ddp->src_node)? 1 : 0;
169: if (ddp_output(&mp, ddp->src_socket, src_addr_included) != 0) {
170: do {
171: ymp = gbuf_next(mp);
172: gbuf_next(mp) = 0;
173: gbuf_freem(mp);
174: mp = ymp;
175: } while (mp);
176: }
177: return;
178: }
179: }
180: if (gref && !DDP_SOCKENTRY(gref)) {
181: data_error(ENOTCONN, mp, gref);
182: return;
183: }
184:
185: if ((error = ddp_output(&mp, DDP_SOCKNUM(gref), 0)) != 0)
186: if (gref)
187: data_error(error, mp, gref);
188: else
189: gbuf_freem(mp);
190: return;
191:
192: case MSG_IOCTL :
193: iocbp = (ioc_t *)gbuf_rptr(mp);
194: if (DDP_IOC_MYIOCTL(iocbp->ioc_cmd)) {
195: switch(iocbp->ioc_cmd) {
196: case DDP_IOC_GET_CFG :
197: if (gbuf_cont(mp))
198: gbuf_freem(gbuf_cont(mp));
199: if ((gbuf_cont(mp) = gbuf_alloc(sizeof(at_ddp_cfg_t),
200: PRI_MED)) == NULL) {
201: if (gref == 0) {
202: iocbp->ioc_error = ENOBUFS;
203: gbuf_set_type(mp, MSG_IOCNAK);
204: if (iocbp->ioc_error == 3)
205: atp_input(mp);
206: else
207: adsp_input(mp);
208: } else
209: ioc_ack(ENOBUFS, mp, gref);
210: break;
211: }
212: if (gref == 0) {
213: ddp_get_cfg((at_ddp_cfg_t *)gbuf_rptr(gbuf_cont(mp)),
214: iocbp->ioc_count);
215: } else
216: ddp_get_cfg((at_ddp_cfg_t *)gbuf_rptr(gbuf_cont(mp)),
217: DDP_SOCKNUM(gref));
218: gbuf_wset(gbuf_cont(mp),sizeof(at_ddp_cfg_t));
219: iocbp->ioc_count = sizeof(at_ddp_cfg_t);
220: if (gref == 0) {
221: gbuf_set_type(mp, MSG_IOCACK);
222: error = iocbp->ioc_error;
223: iocbp->ioc_error = 0;
224: if (error == 3)
225: atp_input(mp);
226: else
227: adsp_input(mp);
228: } else
229: ioc_ack(0, mp, gref);
230: break;
231: case DDP_IOC_GET_STATS :
232: if (gbuf_cont(mp))
233: gbuf_freem(gbuf_cont(mp));
234: if ((gbuf_cont(mp) = gbuf_alloc(sizeof(at_ddp_stats_t),
235: PRI_MED)) == NULL) {
236: ioc_ack(ENOBUFS, mp, gref);
237: break;
238: }
239: ddp_get_stats(
240: (at_ddp_stats_t *)gbuf_rptr(gbuf_cont(mp)));
241: gbuf_wset(gbuf_cont(mp),sizeof(at_ddp_stats_t));
242: iocbp->ioc_count = sizeof(at_ddp_stats_t);
243: ioc_ack(0, mp, gref);
244: break;
245: case DDP_IOC_BIND_SOCK :
246: if ((iocbp->ioc_count < sizeof(at_socket)) ||
247: (gbuf_cont(mp) == NULL) ||
248: (gbuf_len(gbuf_cont(mp)) < sizeof(at_socket))) {
249: ioc_ack(EMSGSIZE, mp, gref);
250: break;
251: }
252: socket.number= *(at_socket *)gbuf_rptr(gbuf_cont(mp));
253: socket.flags = 0;
254: socket.sock_u.gref = gref;
255: socket.dev = (void *)gref->info;
256: if ((error = ddp_bind_socket(&socket)) != 0) {
257: ioc_ack(error, mp, gref);
258: break;
259: } else {
260: DDP_SOCKENTRY(gref) = &ddp_socket[socket.number];
261: DDP_SOCKENTRY(gref)->otChecksum = 0;
262: DDP_SOCKENTRY(gref)->otType = 0;
263: DDP_SOCKENTRY(gref)->otPeerAddr = 0;
264: ddp_socket[socket.number].dev = (void *)gref->info;
265: *(at_socket *)gbuf_rptr(gbuf_cont(mp)) = socket.number;
266: ioc_ack(0, mp, gref);
267: }
268: break;
269: case DDP_IOC_SET_PROTO :
270: ((ddp_dev_t *)gref->info)->proto = *(u_char *)gbuf_rptr(gbuf_cont(mp));
271: ioc_ack(0, mp, gref);
272: break;
273: case DDP_IOC_SET_OPTS:
274: if (DDP_SOCKENTRY(gref) == NULL) {
275: ioc_ack(ENOTREADY, mp, gref);
276: break;
277: }
278: if (gbuf_cont(mp) != NULL) {
279: ddpopt = (union at_ddpopt *)gbuf_rptr(gbuf_cont(mp));
280: DDP_SOCKENTRY(gref)->otChecksum = ddpopt->ct.checksum;
281: DDP_SOCKENTRY(gref)->otType = ddpopt->ct.type;
282: }
283: ioc_ack(0, mp, gref);
284: break;
285: case DDP_IOC_GET_OPTS:
286: if (DDP_SOCKENTRY(gref) == NULL) {
287: ioc_ack(ENOTREADY, mp, gref);
288: break;
289: }
290: if ((gbuf_cont(mp) == NULL)
291: && (gbuf_cont(mp) = gbuf_alloc(sizeof(union at_ddpopt),
292: PRI_MED)) == NULL) {
293: ioc_ack(ENOBUFS, mp, gref);
294: break;
295: }
296: gbuf_wset(gbuf_cont(mp),sizeof(union at_ddpopt));
297: ddpopt = (union at_ddpopt *)gbuf_rptr(gbuf_cont(mp));
298: ddpopt->ct.checksum = DDP_SOCKENTRY(gref)->otChecksum;
299: ddpopt->ct.type = DDP_SOCKENTRY(gref)->otType;
300: ioc_ack(0, mp, gref);
301: break;
302: case DDP_IOC_GET_SOCK:
303: case DDP_IOC_GET_PEER:
304: if (DDP_SOCKENTRY(gref) == NULL) {
305: ioc_ack(ENOTREADY, mp, gref);
306: break;
307: }
308: if ((gbuf_cont(mp) == NULL)
309: && (gbuf_cont(mp) = gbuf_alloc(sizeof(at_inet_t),
310: PRI_MED)) == NULL) {
311: ioc_ack(ENOBUFS, mp, gref);
312: break;
313: }
314: gbuf_wset(gbuf_cont(mp),sizeof(at_inet_t));
315: addr = (at_inet_t *)gbuf_rptr(gbuf_cont(mp));
316: if (iocbp->ioc_cmd == DDP_IOC_GET_SOCK) {
317: bzero((char *)addr, sizeof(at_inet_t));
318: addr->socket = DDP_SOCKENTRY(gref)->number;
319: if (ifID_table[IFID_HOME]) {
320: addr->node =
321: ifID_table[IFID_HOME]->ifThisNode.atalk_node;
322: *(unsigned short *)addr->net = *(unsigned short *)
323: ifID_table[IFID_HOME]->ifThisNode.atalk_net;
324: }
325: } else
326: *addr = *(at_inet_t *)&DDP_SOCKENTRY(gref)->otPeerAddr;
327: ioc_ack(0, mp, gref);
328: break;
329: case DDP_IOC_SET_PEER:
330: if (DDP_SOCKENTRY(gref) == NULL) {
331: ioc_ack(ENOTREADY, mp, gref);
332: break;
333: }
334: if (gbuf_cont(mp) == NULL) {
335: ioc_ack(EINVAL, mp, gref);
336: break;
337: }
338: *(at_inet_t *)&DDP_SOCKENTRY(gref)->otPeerAddr =
339: *(at_inet_t *)gbuf_rptr(gbuf_cont(mp));
340: ioc_ack(0, mp, gref);
341: break;
342: }
343: } else if (ZIP_IOC_MYIOCTL(iocbp->ioc_cmd)) {
344: zip_ioctl(gref, mp);
345: break;
346: } else {
347: /* Unknown ioctl */
348: ioc_ack(EINVAL, mp, gref);
349: }
350: break;
351: case MSG_PROTO:
352: if (((ddp_dev_t *)gref->info)->flags & DDPF_SI)
353: si_ddp_proto_req(gref, mp);
354: else
355: gbuf_freem(mp);
356: break;
357: case MSG_CTL:
358: /* *** this should never happen *** */
359: kprintf("ddp_putmsg: MSG_CTL received/n");
360: gbuf_freem(mp);
361: break;
362: case MSG_IOCACK:
363: ddp_stop_ack(gref, mp);
364: break;
365: default :
366: gbuf_freem(mp);
367: break;
368: }
369: return;
370: } /* ddp_putmsg */
371:
372: char *
373: ddps_init()
374: { register int i;
375: register ddp_dev_t *d;
376:
377: for (i=0, d=ddp_devs; i < DDP_SOCKET_LAST;i++, d++)
378: d->sock_entry = NULL;
379:
380: /* A non-zero value to keep ddp_init happy */
381: return ((char *)1);
382: }
383:
384:
385: int ddps_shutdown(grefInput)
386: gref_t *grefInput;
387: {
388: /* Network is shutting down... send error messages up on each open
389: * socket
390: */
391: register gbuf_t *mp, *mp2;
392: register gref_t *gref;
393: register at_socket socket;
394: register ddp_socket_t *socketp;
395: register int do_timeout = 0;
396:
397: if ((mp = gbuf_alloc(1, PRI_HI)) == NULL) {
398: goto later;
399: }
400:
401: gbuf_wset(mp, 1);
402: gbuf_set_type(mp, MSG_ERROR);
403: *gbuf_rptr(mp) = ESHUTDOWN;
404:
405: for (socket = 1, socketp = &ddp_socket[1]; socket <= DDP_SOCKET_LAST;
406: socket++, socketp++) {
407: if (gref = socketp->sock_u.gref) {
408: if (mp2 = (gbuf_t *)gbuf_copym(mp)) {
409: if (socketp->flags & DDP_CALL_HANDLER)
410: (*socketp->sock_u.handler)(mp2, 0);
411: else
412: atalk_putnext(gref, mp2);
413: } else {
414: /* Out of buffers, wait a while...
415: */
416: do_timeout = 1;
417: ddp_devs[socketp->number].flags
418: |= DDPF_SHUTDOWN;
419: continue;
420: }
421: }
422: }
423:
424: gbuf_freem(mp);
425: if (do_timeout)
426: goto later;
427: return;
428:
429: later:
430: atalk_timeout(ddps_shutdown, grefInput, SYS_HZ/10);
431: return;
432: }
433:
434: gbuf_t *ddp_compress_msg(mp)
435: register gbuf_t *mp;
436: {
437: register gbuf_t *tmp;
438:
439: while (gbuf_len(mp) == 0) {
440: tmp = mp;
441: mp = gbuf_cont(mp);
442: gbuf_freeb(tmp);
443:
444: if (mp == NULL)
445: break;
446: }
447: return (mp);
448: }
449:
450: int
451: si_ddp_proto_req(gref, mp)
452: gref_t *gref;
453: gbuf_t *mp;
454: {
455: at_ddp_t *ddp;
456: at_inet_t *remaddr;
457: gbuf_t *xmp = gbuf_cont(mp);
458:
459: if ((DDP_SOCKENTRY(gref) == NULL) || (xmp == NULL)) {
460: gbuf_freem(mp);
461: return(-1);
462: }
463:
464: if (gbuf_len(mp) == 1) {
465: remaddr = (at_inet_t *)&DDP_SOCKENTRY(gref)->otPeerAddr;
466: if (remaddr->socket == 0) {
467: gbuf_freem(mp);
468: return(-1);
469: }
470: } else
471: remaddr = (at_inet_t *)gbuf_rptr(mp);
472:
473: gbuf_rinc(xmp,DDP_X_HDR_SIZE);
474: ddp = (at_ddp_t *)gbuf_rptr(mp);
475: *(unsigned short *)&ddp->checksum = DDP_SOCKENTRY(gref)->otChecksum;
476: ddp->length = gbuf_len(xmp);
477: ddp->dst_socket = remaddr->socket;
478: ddp->dst_node = remaddr->node;
479: ddp->type = DDP_SOCKENTRY(gref)->otType;
480: *(unsigned short *)&ddp->dst_net = *(unsigned short *)&remaddr->net;
481: gbuf_freeb(mp);
482: if (ddp_output(&xmp, DDP_SOCKENTRY(gref)->number, 0) != 0) {
483: gbuf_freem(xmp);
484: return(-1);
485: }
486:
487: return( 0);
488: }
489:
490: int
491: si_ddp_input(gref, mp)
492: gref_t *gref;
493: gbuf_t *mp;
494: {
495: gbuf_t *xmp;
496: at_ddp_t *ddp;
497: at_inet_t *remaddr;
498:
499: /*
500: * allocate a buffer for the M_PROTO
501: */
502: if ((xmp = gbuf_alloc(sizeof(at_inet_t), PRI_MED)) == NULL) {
503: gbuf_freem(mp);
504: return(ENOBUFS);
505: }
506: gbuf_cont(xmp) = mp;
507:
508: /*
509: * construct the M_PROTO
510: */
511: ddp = (at_ddp_t *)gbuf_rptr(mp);
512: gbuf_rinc(mp,DDP_X_HDR_SIZE);
513: gbuf_wset(xmp,sizeof(at_inet_t));
514: remaddr = (at_inet_t *)gbuf_rptr(xmp);
515: remaddr->socket = ddp->src_socket;
516: remaddr->node = ddp->src_node;
517: *(unsigned short *)&remaddr->net = *(unsigned short *)&ddp->src_net;
518: gbuf_set_type(xmp, MSG_PROTO);
519:
520: /*
521: * send the M_PROTO upstream
522: */
523: atalk_putnext(gref, xmp);
524: return(0);
525: }
526:
527: /*
528: * stop DDP now
529: */
530: void
531: ddp_stop(mioc, gref)
532: gbuf_t *mioc;
533: gref_t *gref;
534: {
535: unsigned char flag;
536: int k, s, *x_wptr;
537: ddp_dev_t *dev;
538: gbuf_t *m = gbuf_cont(mioc);
539:
540: ATDISABLE(s, ddpinp_lock);
541: if ((flag = *gbuf_rptr(m)) != 0)
542: ddp_off_flag = 1;
543:
544: x_wptr = (int *)gbuf_wptr(m);
545: for (k=0; k < (DDP_SOCKET_LAST+1); k++) {
546: dev = &ddp_devs[k];
547: if ((dev->flags == 0) || (dev->pid == 0))
548: continue;
549: *(int *)gbuf_wptr(m) = dev->pid;
550: gbuf_winc(m,sizeof(int));
551: }
552: ATENABLE(s, ddpinp_lock);
553:
554: while (x_wptr != (int *)gbuf_wptr(m)) {
555: dPrintf(D_M_DDP,D_L_TRACE, ("ddp_stop: pid=%d\n", *x_wptr));
556: x_wptr++;
557: }
558:
559: ddp_ack_m = mioc;
560: ddp_ack_gref = gref;
561: gbuf_rptr(m)[1] = 0;
562: gbuf_set_type(m, MSG_IOCTL);
563: atp_input(m);
564: }
565:
566: static void
567: ddp_stop_ack(gref, m)
568: gref_t *gref;
569: gbuf_t *m;
570: {
571: static int gotADSPinput = 0;
572:
573: if (!gotADSPinput) {
574: dPrintf(D_M_DDP,D_L_INFO,
575: ("ddp_stop_ack: CHECK_STATE...1\n"));
576: gotADSPinput = 1;
577: gbuf_set_type(m, MSG_IOCTL);
578: adsp_input(m);
579: } else {
580: dPrintf(D_M_DDP,D_L_INFO,
581: ("ddp_stop_ack: CHECK_STATE...2\n"));
582: gotADSPinput = 0;
583: gbuf_rinc(m,sizeof(int));
584: gbuf_set_type(m, MSG_DATA);
585: ((ioc_t *)gbuf_rptr(ddp_ack_m))->ioc_count = gbuf_msgsize(m);
586: ioc_ack(0, ddp_ack_m, ddp_ack_gref);
587: }
588: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.