|
|
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) 1996-1998 Apple Computer, Inc.
24: * All Rights Reserved.
25: */
26:
27: /* Modified for MP, 1996 by Tuyen Nguyen
28: * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
29: */
30: #include <sys/errno.h>
31: #include <sys/types.h>
32: #include <sys/param.h>
33: #include <machine/spl.h>
34: #include <sys/systm.h>
35: #include <sys/kernel.h>
36: #include <sys/proc.h>
37: #include <sys/filedesc.h>
38: #include <sys/fcntl.h>
39: #include <sys/mbuf.h>
40: #include <sys/ioctl.h>
41: #include <sys/malloc.h>
42: #include <sys/socket.h>
43:
44: #include <netat/sysglue.h>
45: #include <netat/appletalk.h>
46: #include <netat/ddp.h>
47: #include <netat/at_pcb.h>
48: #include <netat/atp.h>
49: #include <netat/debug.h>
50:
51: static void atp_trans_complete();
52: void atp_x_done();
53: extern void atp_req_timeout();
54:
55: /*
56: * Decide what to do about received messages
57: * Version 1.7 of atp_read.c on 89/02/09 17:53:16
58: */
59:
60: void atp_treq_event(gref)
61: register gref_t *gref;
62: {
63: register gbuf_t *m;
64: register struct atp_state *atp;
65:
66: atp = (struct atp_state *)gref->info;
67: if (atp->dflag)
68: atp = (struct atp_state *)atp->atp_msgq;
69:
70: if (atp->dflag) {
71: if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) != NULL) {
72: gbuf_set_type(m, MSG_IOCTL);
73: gbuf_wset(m,sizeof(ioc_t));
74: ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_GET_POLL;
75: atp_wput(gref, m);
76: }
77: }
78: else if ((m = gbuf_alloc(1, PRI_HI)) != NULL) {
79: *gbuf_rptr(m) = 0;
80: gbuf_wset(m,1);
81: atalk_putnext(gref, m);
82: }
83:
84: if (m == 0)
85: timeout(atp_treq_event, gref, 10);
86: }
87:
88: void atp_rput(gref, m)
89: gref_t *gref;
90: gbuf_t *m;
91: {
92: register at_atp_t *athp;
93: register struct atp_state *atp;
94: register int s, s_gen;
95: gbuf_t *m_asp = NULL;
96:
97: atp = (struct atp_state *)gref->info;
98: if (atp->dflag)
99: atp = (struct atp_state *)atp->atp_msgq;
100:
101: switch(gbuf_type(m)) {
102: case MSG_DATA:
103: /*
104: * Decode the message, make sure it is an atp
105: * message
106: */
107: if (((AT_DDP_HDR(m))->type != DDP_ATP) ||
108: (atp->atp_flags & ATP_CLOSING)) {
109: gbuf_freem(m);
110: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR),
111: ("atp_rput: dropping MSG, not atp\n"));
112: break;
113: }
114:
115: athp = AT_ATP_HDR(m);
116: dPrintf(D_M_ATP_LOW, D_L_INPUT,
117: ("atp_rput MSG_DATA: %s (%d)\n",
118: (athp->cmd == ATP_CMD_TRESP)? "TRESP":
119: (athp->cmd == ATP_CMD_TREL)? "TREL":
120: (athp->cmd == ATP_CMD_TREQ)? "TREQ": "unknown",
121: athp->cmd));
122: trace_mbufs(D_M_ATP_LOW, " r", m);
123:
124: switch (athp->cmd) {
125:
126: case ATP_CMD_TRESP:
127: {
128: register struct atp_trans *trp;
129: register int seqno;
130: register at_ddp_t *ddp;
131:
132: /*
133: * we just got a response, find the trans record
134: */
135:
136: ATDISABLE(s, atp->atp_lock);
137: for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
138: if (trp->tr_tid == UAS_VALUE(athp->tid))
139: break;
140: }
141:
142: /*
143: * If we can't find one then ignore the message
144: */
145: seqno = athp->bitmap;
146: if (trp == NULL) {
147: ATENABLE(s, atp->atp_lock);
148: ddp = AT_DDP_HDR(m);
149: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR),
150: ("atp_rput: dropping TRESP, no trp,tid=%d,loc=%d,rem=%d.%d,seqno=%d\n",
151: UAS_VALUE(athp->tid),
152: ddp->dst_socket,ddp->src_node,ddp->src_socket,seqno));
153: gbuf_freem(m);
154: return;
155: }
156:
157: /*
158: * If no longer valid, drop it
159: */
160: if (trp->tr_state == TRANS_FAILED) {
161: ATENABLE(s, atp->atp_lock);
162: ddp = AT_DDP_HDR(m);
163: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR),
164: ("atp_rput: dropping TRESP, failed trp,tid=%d,loc=%d,rem=%d.%d\n",
165: UAS_VALUE(athp->tid),
166: ddp->dst_socket, ddp->src_node, ddp->src_socket));
167: gbuf_freem(m);
168: return;
169: }
170:
171: /*
172: * If we have already received it, ignore it
173: */
174: if (!(trp->tr_bitmap&atp_mask[seqno]) || trp->tr_rcv[seqno]) {
175: ATENABLE(s, atp->atp_lock);
176: ddp = AT_DDP_HDR(m);
177: dPrintf(D_M_ATP_LOW, (D_L_INPUT|D_L_ERROR),
178: ("atp_rput: dropping TRESP, duplicate,tid=%d,loc=%d,rem=%d.%d,seqno=%d\n",
179: UAS_VALUE(athp->tid),
180: ddp->dst_socket, ddp->src_node, ddp->src_socket, seqno));
181: gbuf_freem(m);
182: return;
183: }
184:
185: /*
186: * Update the received packet bitmap
187: */
188: if (athp->eom)
189: trp->tr_bitmap &= atp_lomask[seqno];
190: else
191: trp->tr_bitmap &= ~atp_mask[seqno];
192:
193: /*
194: * Save the message in the trans record
195: */
196: trp->tr_rcv[seqno] = m;
197:
198: /*
199: * If it isn't the first message then
200: * can the header
201: */
202: if (seqno)
203: gbuf_rinc(m,DDP_X_HDR_SIZE);
204:
205: /*
206: * If we now have all the responses then return
207: * the message to the user
208: */
209: if (trp->tr_bitmap == 0) {
210: ATENABLE(s, atp->atp_lock);
211:
212: /*
213: * Cancel the request timer and any
214: * pending transmits
215: */
216: atp_untimout(atp_req_timeout, trp);
217:
218: /*
219: * Send the results back to the user
220: */
221: atp_x_done(trp);
222: return;
223: }
224: if (athp->sts) {
225: /*
226: * If they want treq again, send them
227: */
228: ATENABLE(s, atp->atp_lock);
229: atp_untimout(atp_req_timeout, trp);
230: atp_send(trp);
231: return;
232: }
233: ATENABLE(s, atp->atp_lock);
234: return;
235: }
236:
237: case ATP_CMD_TREL:
238: { register struct atp_rcb *rcbp;
239: register at_ddp_t *ddp;
240:
241: /*
242: * Search for a matching transaction
243: */
244: ddp = AT_DDP_HDR(m);
245:
246: ATDISABLE(s, atp->atp_lock);
247: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
248: if (rcbp->rc_tid == UAS_VALUE(athp->tid) &&
249: rcbp->rc_socket.node == ddp->src_node &&
250: rcbp->rc_socket.net == NET_VALUE(ddp->src_net) &&
251: rcbp->rc_socket.socket == ddp->src_socket) {
252: /*
253: * Mark the rcb released
254: */
255: rcbp->rc_not_sent_bitmap = 0;
256: if (rcbp->rc_state == RCB_SENDING)
257: rcbp->rc_state = RCB_RELEASED;
258: else
259: {
260: ddp = 0;
261: atp_rcb_free(rcbp);
262: ATENABLE(s, atp->atp_lock);
263: }
264: break;
265: }
266: }
267:
268: if (ddp)
269: ATENABLE(s, atp->atp_lock);
270: gbuf_freem(m);
271: return;
272: }
273:
274:
275: case ATP_CMD_TREQ:
276: { register struct atp_rcb *rcbp;
277: register at_ddp_t *ddp;
278: gbuf_t *m2;
279:
280: /*
281: * If it is a request message, first
282: * check to see
283: * if matches something in our active
284: * request queue
285: */
286: ddp = AT_DDP_HDR(m);
287:
288: ATDISABLE(s, atp->atp_lock);
289: for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
290: if (rcbp->rc_tid == UAS_VALUE(athp->tid) &&
291: rcbp->rc_socket.node == ddp->src_node &&
292: rcbp->rc_socket.net == NET_VALUE(ddp->src_net) &&
293: rcbp->rc_socket.socket == ddp->src_socket)
294: break;
295: }
296: /*
297: * If this is a new req then do
298: * something with it
299: */
300: if (rcbp == NULL) {
301: /*
302: * see if it matches something in the
303: * attached request queue
304: * if it does, just release the message
305: * and go on about our buisness
306: */
307: /* we just did this, why do again? -jjs 4-10-95 */
308: for (rcbp = atp->atp_attached.head; rcbp; rcbp = rcbp->rc_list.next) {
309: if (rcbp->rc_tid == UAS_VALUE(athp->tid) &&
310: rcbp->rc_socket.node == ddp->src_node &&
311: rcbp->rc_socket.net == NET_VALUE(ddp->src_net) &&
312: rcbp->rc_socket.socket == ddp->src_socket) {
313: ATENABLE(s, atp->atp_lock);
314: gbuf_freem(m);
315: dPrintf(D_M_ATP_LOW, D_L_INPUT,
316: ("atp_rput: dropping TREQ, matches req queue\n"));
317: return;
318: }
319: }
320:
321: /*
322: * assume someone is interested in
323: * in an asynchronous incoming request
324: */
325: ATENABLE(s, atp->atp_lock);
326: if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
327: gbuf_freem(m);
328: return;
329: }
330: rcbp->rc_state = RCB_UNQUEUED;
331: ATDISABLE(s, atp->atp_lock);
332:
333: rcbp->rc_local_node = ddp->dst_node;
334: NET_NET(rcbp->rc_local_net, ddp->dst_net);
335: rcbp->rc_socket.socket = ddp->src_socket;
336: rcbp->rc_socket.node = ddp->src_node;
337: rcbp->rc_socket.net = NET_VALUE(ddp->src_net);
338: rcbp->rc_tid = UAS_VALUE(athp->tid);
339: rcbp->rc_bitmap = athp->bitmap;
340: rcbp->rc_not_sent_bitmap = athp->bitmap;
341: rcbp->rc_xo = athp->xo;
342: /*
343: * if async then send it as
344: * data
345: * otherwise, it is a synchronous ioctl so
346: * complete it
347: */
348: if (atp->dflag) { /* for ASP? */
349: if ((m2 = gbuf_alloc(sizeof(ioc_t), PRI_HI))) {
350: gbuf_set_type(m2, MSG_DATA);
351: gbuf_wset(m2,sizeof(ioc_t));
352: ((ioc_t *)gbuf_rptr(m2))->ioc_cmd = AT_ATP_GET_POLL;
353: m_asp = m2;
354: }
355: } else if ((m2 = gbuf_alloc(1, PRI_HI))) {
356: *gbuf_rptr(m2) = 0;
357: gbuf_wset(m2,1);
358: atalk_putnext(gref, m2);
359: }
360: if (m2 == 0) {
361: dPrintf(D_M_ATP,D_L_WARNING,
362: ("atp_rput: out of buffer for TREQ\n"));
363: timeout(atp_treq_event, gref, 10);
364: }
365: rcbp->rc_ioctl = m;
366:
367: /*
368: * move it to the attached list
369: */
370: dPrintf(D_M_ATP_LOW, D_L_INPUT,
371: ("atp_rput: moving to attached list\n"));
372: rcbp->rc_state = RCB_PENDING;
373: ATP_Q_APPEND(atp->atp_attached, rcbp, rc_list);
374: if (m_asp != NULL) {
375: ATENABLE(s, atp->atp_lock);
376: atp_req_ind(atp, m_asp);
377: return;
378: }
379: } else {
380: dPrintf(D_M_ATP_LOW, D_L_INPUT,
381: ("atp_rput: found match, state:%d\n",
382: rcbp->rc_state));
383:
384: /*
385: * Otherwise we have found a matching request
386: * look for what to do
387: */
388: switch (rcbp->rc_state) {
389: case RCB_RESPONDING:
390: case RCB_RESPONSE_FULL:
391: /*
392: * If it is one we have in progress
393: * (either have all the responses
394: * or are waiting for them)
395: * update the bitmap and resend
396: * the replies
397: */
398: ATDISABLE(s_gen, atpgen_lock);
399: if (rcbp->rc_timestamp) {
400: rcbp->rc_timestamp = time.tv_sec;
401: if (rcbp->rc_timestamp == 0)
402: rcbp->rc_timestamp = 1;
403: }
404: ATENABLE(s_gen, atpgen_lock);
405: rcbp->rc_bitmap = athp->bitmap;
406: rcbp->rc_not_sent_bitmap = athp->bitmap;
407: ATENABLE(s, atp->atp_lock);
408: gbuf_freem(m);
409: atp_reply(rcbp);
410: return;
411:
412: case RCB_RELEASED:
413: default:
414: /*
415: * If we have a release or
416: * we haven't sent any data yet
417: * ignore the request
418: */
419: ATENABLE(s, atp->atp_lock);
420: gbuf_freem(m);
421: return;
422: }
423: }
424: ATENABLE(s, atp->atp_lock);
425: return;
426: }
427:
428: default:
429: gbuf_freem(m);
430: break;
431: }
432: break;
433:
434: case MSG_IOCACK:
435: if (atp->dflag)
436: asp_ack_reply(gref, m);
437: else
438: atalk_putnext(gref, m);
439: break;
440:
441: case MSG_IOCNAK:
442: if (atp->dflag)
443: asp_nak_reply(gref, m);
444: else
445: atalk_putnext(gref, m);
446: break;
447:
448: default:
449: gbuf_freem(m);
450: }
451: } /* atp_rput */
452:
453: void
454: atp_x_done(trp)
455: register struct atp_trans *trp;
456: {
457: struct atp_state *atp;
458: gbuf_t *m;
459:
460: if ( !trp->tr_xo)
461: atp_trans_complete(trp);
462: else {
463: /*
464: * If execute once send a release
465: */
466: if ((m = (gbuf_t *)atp_build_release(trp)) != NULL) {
467: AT_DDP_HDR(m)->src_socket = ((struct atp_state *)
468: trp->tr_queue)->atp_socket_no;
469: DDP_OUTPUT(m);
470: /*
471: * Now send back the transaction reply to the process
472: * or notify the process if required
473: */
474: atp_trans_complete(trp);
475: } else {
476:
477: atp = trp->tr_queue;
478: trp->tr_state = TRANS_RELEASE;
479: timeout(atp_x_done, trp, 10);
480: }
481: }
482: }
483:
484: static void
485: atp_trans_complete(trp)
486: register struct atp_trans *trp;
487: { register gbuf_t *m;
488: register int type;
489: struct atp_state *atp;
490:
491: /* we could gbuf_freem(trp->tr_xmt) here if were not planning to
492: re-use the mbuf later */
493: m = trp->tr_xmt;
494: trp->tr_xmt = NULL;
495: trp->tr_state = TRANS_DONE;
496:
497: if (gbuf_cont(m) == NULL) /* issued via the new interface */
498: type = AT_ATP_ISSUE_REQUEST_NOTE;
499: else {
500: type = ((ioc_t *)(gbuf_rptr(m)))->ioc_cmd;
501: /*
502: * free any data following the ioctl blk
503: */
504: gbuf_freem(gbuf_cont(m));
505: gbuf_cont(m) = NULL;
506: }
507: dPrintf(D_M_ATP_LOW, D_L_INPUT, ("atp_trans_comp: trp=0x%x type = %s\n",
508: (u_int) trp,
509: (type==AT_ATP_ISSUE_REQUEST)? "AT_ATP_ISSUE_REQUEST":
510: (type==AT_ATP_ISSUE_REQUEST_NOTE)? "AT_ATP_ISSUE_REQUEST_NOTE" :
511: "unknown"));
512:
513: switch(type) {
514: case AT_ATP_ISSUE_REQUEST:
515: atp = trp->tr_queue;
516: if (atp->dflag) {
517: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
518: ((ioc_t *)gbuf_rptr(m))->ioc_error = 0;
519: ((ioc_t *)gbuf_rptr(m))->ioc_rval = trp->tr_tid;
520: ((ioc_t *)gbuf_rptr(m))->ioc_cmd = AT_ATP_REQUEST_COMPLETE;
521: gbuf_set_type(m, MSG_IOCTL);
522: atp_rsp_ind(trp, m);
523: } else {
524: if (trp->tr_bdsp == NULL) {
525: gbuf_freem(m);
526: if (trp->tr_rsp_wait)
527: thread_wakeup(&trp->tr_event);
528: } else {
529: gbuf_set_type(m, MSG_IOCACK);
530: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
531: ((ioc_t *)gbuf_rptr(m))->ioc_error = 0;
532: ((ioc_t *)gbuf_rptr(m))->ioc_rval = 0;
533: atalk_putnext(trp->tr_queue->atp_gref, m);
534: }
535: }
536: break;
537:
538: case AT_ATP_ISSUE_REQUEST_NOTE:
539: gbuf_wset(m,1);
540: *gbuf_rptr(m) = 1;
541: gbuf_set_type(m, MSG_DATA);
542: atalk_putnext(trp->tr_queue->atp_gref, m);
543: break;
544: }
545: } /* atp_trans_complete */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.