|
|
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 February 20, 1995 by Tuyen Nguyen
27: * Modified for MP, 1996 by Tuyen Nguyen
28: * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
29: */
30:
31: #include <sys/errno.h>
32: #include <sys/types.h>
33: #include <sys/param.h>
34: #include <machine/spl.h>
35: #include <sys/systm.h>
36: #include <sys/kernel.h>
37: #include <sys/proc.h>
38: #include <sys/filedesc.h>
39: #include <sys/fcntl.h>
40: #include <sys/mbuf.h>
41: #include <sys/ioctl.h>
42: #include <sys/malloc.h>
43: #include <sys/socket.h>
44: #include <sys/socketvar.h>
45:
46: #include <net/if.h>
47:
48: #include <netat/appletalk.h>
49: #include <netat/sysglue.h>
50: #include <netat/at_pcb.h>
51: #include <netat/atp.h>
52: #include <netat/lap.h>
53: #include <netat/ddp.h>
54: #include <netat/asp.h>
55: #include <netat/at_var.h>
56: #include <netat/debug.h>
57:
58: static int loop_cnt;
59: #define CHK_LOOP(str) { \
60: if (loop_cnt++ > 100) { \
61: kprintf("%s", str); \
62: break; \
63: } \
64: }
65:
66: #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
67: #define aspCMDsize (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
68: #define SCBS_PER_BLK 16
69: #define TICKS_PER_SEC HZ
70: #define SESS_TMO_RES 2
71: #define DEF_SESS_TMO 120
72: #define NEXT_SEQ_NUM(x) (x = (x == 65535) ? 0 : (x + 1))
73: #define MAX_RCV_CNT 5
74: #define BAD_REMADDR(addr) \
75: ( (*(long *)&scb->rem_addr != *(long *)&addr) \
76: && ((scb->rem_addr.net != addr.net) \
77: || (scb->rem_addr.node != addr.node)) )
78:
79: int ASPputmsg();
80: int ASPgetmsg();
81: void asp_init();
82: void asp_ack_reply();
83: void asp_nak_reply();
84: void asp_clock();
85: int asp_open();
86: int asp_close();
87: int asp_wput();
88: void atp_retry_req();
89: StaticProc asp_scb_t *asp_find_scb();
90: StaticProc asp_scb_t *asp_scb_alloc();
91:
92: StaticProc void asp_putnext();
93: StaticProc void asp_iocack();
94: StaticProc void asp_iocnak();
95: StaticProc void asp_dequeue_scb();
96: StaticProc void asp_scb_free();
97: StaticProc void asp_timout();
98: StaticProc void asp_untimout();
99: StaticProc void asp_hangup();
100: StaticProc void asp_send_tickle();
101: StaticProc void asp_accept();
102: StaticProc int asp_send_req();
103:
104: extern at_ifaddr_t *ifID_home;
105: extern int atp_pidM[];
106: extern gref_t *atp_inputQ[];
107: gbuf_t *scb_resource_m = 0;
108: unsigned char asp_inpC[256];
109: asp_scb_t *asp_scbQ[256];
110:
111: static at_retry_t asp_def_retry = {2, -1, 1};
112: static unsigned char scb_tmo_cnt;
113: asp_scb_t *scb_used_list;
114: static asp_scb_t *scb_tmo_list;
115: asp_scb_t *scb_free_list;
116: atlock_t aspall_lock, asptmo_lock;
117:
118: int
119: asp_readable(gref)
120: gref_t *gref;
121: {
122: return (((asp_scb_t *)gref->info)->sess_ioc ? 1 : 0);
123: }
124:
125: void
126: asp_init()
127: {
128: scb_tmo_cnt = 1;
129: scb_tmo_list = 0;
130: scb_used_list = 0;
131: scb_free_list = 0;
132: bzero(asp_inpC, sizeof(asp_inpC));
133: bzero(asp_scbQ, sizeof(asp_scbQ));
134: }
135:
136: /*
137: * the open routine allocates a state structure
138: */
139: int asp_open(gref)
140: gref_t *gref;
141: {
142: int s;
143: asp_scb_t *scb;
144:
145: /*
146: * if no asp structure available, return failure
147: */
148: if ((scb = asp_scb_alloc()) == 0)
149: return ENOBUFS;
150:
151: /*
152: * initialize the gref data structure
153: */
154: gref->info = (void *)scb;
155: gref->readable = asp_readable;
156:
157: /*
158: * initialize the scb data structure
159: */
160: scb->dflag = 1;
161: scb->magic_num = 222;
162: scb->state = ASPSTATE_Idle;
163: scb->pid = gref->pid;
164: scb->gref = gref;
165: scb->session_timer = DEF_SESS_TMO;
166: scb->cmd_retry = asp_def_retry;
167: ATDISABLE(s, aspall_lock);
168: if ((scb->next_scb = scb_used_list) != 0)
169: scb->next_scb->prev_scb = scb;
170: scb_used_list = scb;
171: ATENABLE(s, aspall_lock);
172:
173: /*
174: * return success
175: */
176: dPrintf(D_M_ASP, D_L_INFO, ("asp_open: pid=%d\n", scb->pid));
177: return 0;
178: } /* asp_open */
179:
180: /*
181: * the close routine frees all the data structures
182: */
183: int
184: asp_close(gref)
185: gref_t *gref;
186: {
187: int s;
188: unsigned char sock_num;
189: asp_scb_t *scb, *new_scb;
190: gbuf_t *m;
191:
192: scb = (asp_scb_t *)gref->info;
193: dPrintf(D_M_ASP, D_L_INFO, ("asp_close: loc=%d\n",
194: scb->loc_addr.socket));
195:
196: if (scb->pid && scb->sess_ioc && (scb->dflag != 1)) {
197: /*
198: * send the CloseSess response to peer
199: */
200: if (gbuf_type(scb->sess_ioc) != MSG_PROTO) {
201: ATDISABLE(s, scb->lock);
202: m = scb->sess_ioc;
203: scb->sess_ioc = gbuf_next(m);
204: ATENABLE(s, scb->lock);
205: atp_send_rsp(scb->gref, m, TRUE);
206: }
207: }
208:
209: if (scb->atp_state) {
210: sock_num = scb->loc_addr.socket;
211: ATDISABLE(s, aspall_lock);
212: if ((scb->dflag != 1) && scb->stat_msg) {
213: untimeout(atp_retry_req, scb->stat_msg);
214: gbuf_freem(scb->stat_msg);
215: scb->stat_msg = 0;
216: }
217: if (asp_scbQ[sock_num]->next_scb == 0) {
218: asp_scbQ[sock_num] = 0;
219: asp_inpC[sock_num] = 0;
220: ATENABLE(s, aspall_lock);
221: dPrintf(D_M_ASP, D_L_INFO,
222: (" : atp_close(), loc=%d\n", scb->loc_addr.socket));
223: atp_close(gref, 0);
224: } else {
225: asp_inpC[sock_num]--;
226: if (scb == asp_scbQ[sock_num]) {
227: new_scb = scb->next_scb;
228: new_scb->prev_scb = 0;
229: asp_scbQ[sock_num] = new_scb;
230: new_scb->atp_state->atp_gref = new_scb->gref;
231: new_scb->atp_state->pid = new_scb->pid;
232: atp_inputQ[sock_num] = new_scb->gref;
233: } else {
234: if ((scb->prev_scb->next_scb = scb->next_scb) != 0)
235: scb->next_scb->prev_scb = scb->prev_scb;
236: }
237: scb->next_scb = 0;
238: ATENABLE(s, aspall_lock);
239: }
240: } else
241: asp_dequeue_scb(scb);
242:
243: /*
244: * free all allocated blocks if any
245: */
246: ATDISABLE(s, scb->lock);
247: if (scb->stat_msg) {
248: gbuf_freem(scb->stat_msg);
249: scb->stat_msg = 0;
250: }
251: if (scb->sess_ioc) {
252: gbuf_freel(scb->sess_ioc);
253: scb->sess_ioc = 0;
254: }
255: if (scb->req_msgq) {
256: gbuf_freel(scb->req_msgq);
257: scb->req_msgq = 0;
258: }
259:
260: scb->rem_addr.node = 0;
261: ATENABLE(s, scb->lock);
262:
263: /*
264: * stop all timers
265: */
266: scb->tmo_cnt = 0;
267: asp_untimout(asp_hangup, scb);
268: untimeout(asp_send_tickle, (void *)scb); /* added for 2225395 */
269:
270: /*
271: * free the asp session control block
272: */
273: scb->state = ASPSTATE_Close;
274: asp_scb_free(scb);
275: return 0;
276: } /* asp_close */
277:
278: static char *aspStateStr(state)
279: int state;
280: {
281: return ((state==ASPSTATE_Close)? "Close":
282: (state==ASPSTATE_Idle)? "Idle":
283: (state==ASPSTATE_WaitingForGetStatusRsp)? "GetStatusRsp":
284: (state==ASPSTATE_WaitingForOpenSessRsp)? "OpenSessRsp":
285: (state==ASPSTATE_WaitingForCommandRsp)? "CmdRsp":
286: (state==ASPSTATE_WaitingForWriteContinue)? "WriteCont":
287: (state==ASPSTATE_WaitingForWriteRsp)? "WriteRsp":
288: (state==ASPSTATE_WaitingForWriteContinueRsp)? "WriteContRsp":
289: (state==ASPSTATE_WaitingForCloseSessRsp)? "CloseSessRsp":
290: "unknown");
291: }
292:
293: static char *aspCmdStr(aspCmd)
294: int aspCmd;
295: {
296: return ((aspCmd==ASPFUNC_CloseSess)? "CloseSess":
297: (aspCmd==ASPFUNC_Command)? "Command":
298: (aspCmd==ASPFUNC_GetStatus)? "GetStatus":
299: (aspCmd==ASPFUNC_OpenSess)? "OpenSess":
300: (aspCmd==ASPFUNC_Tickle)? "Tickle":
301: (aspCmd==ASPFUNC_Write)? "Write":
302: (aspCmd==ASPFUNC_WriteContinue)? "WriteContinue":
303: (aspCmd==ASPFUNC_Attention)? "Attention":
304: (aspCmd==ASPFUNC_CmdReply)? "CmdReply": "unknown");
305: }
306:
307: static char *aspIOCStr(aspIOC)
308: int aspIOC;
309: {
310: return (
311: (aspIOC==ASPIOC_ClientBind)? "ClientBind":
312: (aspIOC==ASPIOC_CloseSession)? "CloseSession":
313: (aspIOC==ASPIOC_GetLocEntity)? "GetLocEntity":
314: (aspIOC==ASPIOC_GetRemEntity)? "GetRemEntity":
315: (aspIOC==ASPIOC_GetSession)? "GetSession":
316: (aspIOC==ASPIOC_GetStatus)? "GetStatus":
317: (aspIOC==ASPIOC_ListenerBind)? "ListenerBind":
318: (aspIOC==ASPIOC_OpenSession)? "OpenSession":
319: (aspIOC==ASPIOC_StatusBlock)? "StatusBlock":
320: (aspIOC==ASPIOC_SetPid)? "SetPid":
321: (aspIOC==ASPIOC_GetSessId)? "GetSessId":
322: (aspIOC==ASPIOC_EnableSelect)? "EnableSelect":
323: (aspIOC==ASPIOC_Look)? "Look":
324: "unknown"
325: );
326: }
327:
328: #ifdef AT_MBUF_TRACE
329:
330: static char mbuf_str[100];
331: char *mbuf_totals()
332: {
333: sprintf(mbuf_str,
334: /*
335: "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
336: */
337: "dat = %d, prot = %d, ioc = %d, ctl = %d",
338: mbstat.m_mtypes[MSG_DATA], mbstat.m_mtypes[MSG_PROTO], mbstat.m_mtypes[MSG_IOCTL],
339: /*
340: mbstat.m_mtypes[MSG_ERROR], mbstat.m_mtypes[MSG_HANGUP], mbstat.m_mtypes[MSG_IOCACK],
341: mbstat.m_mtypes[MSG_IOCNAK],
342: */
343: mbstat.m_mtypes[MSG_CTL]);
344: return(&mbuf_str[0]);
345: }
346:
347: void trace_beg(str, m)
348: char *str;
349: gbuf_t *m;
350: {
351: int i = 0, j = 0;
352: gbuf_t *mdata, *mchain;
353:
354: if (m)
355: for (i = 0, j = 0, mdata = m, mchain = m; mdata; i++) {
356: mdata = gbuf_cont(mdata);
357: if (!mdata && mchain) {
358: mdata = gbuf_next(mchain);
359: mchain = mdata;
360: j++;
361: }
362: }
363: dPrintf(D_M_ASP, D_L_TRACE,
364: ("%s: %s, m# = %d, c# = %d\n", str, mbuf_totals(), i, j));
365: }
366:
367: void trace_end(str)
368: char *str;
369: {
370: dPrintf(D_M_ASP, D_L_TRACE,
371: (" %s: %s\n", str, mbuf_totals()));
372: }
373: #endif AT_MBUF_TRACE
374:
375: /*
376: * the write routine
377: */
378: int asp_wput(gref, m)
379: gref_t *gref;
380: gbuf_t *m;
381: {
382: int s, err;
383: unsigned char sockSav, sock_num;
384: gbuf_t *mioc, *mdata;
385: ioc_t *iocbp;
386: asp_scb_t *scb, *server_scb, *curr_scb;
387: at_inet_t *addr;
388: asp_word_t aw;
389: union asp_primitives *primitives;
390: asp_status_cmd_t *status_cmd;
391: asp_open_cmd_t *open_cmd;
392: at_retry_t Retry;
393:
394: scb = (asp_scb_t *)gref->info;
395: if (scb->dflag == 0) {
396: atp_wput(gref, m);
397: return 0;
398: }
399:
400: if (gbuf_type(m) != MSG_IOCTL) {
401: dPrintf(D_M_ASP, D_L_WARNING,
402: ("asp_wput: UNKNOWN message, type=%d\n",
403: gbuf_type(m)));
404: gbuf_freem(m);
405: return 0;
406: }
407:
408: mioc = m;
409: iocbp = (ioc_t *)gbuf_rptr(mioc);
410:
411: dPrintf(D_M_ASP_LOW, D_L_INFO,
412: ("asp_wput: %s, loc=%d, state=%s\n",
413: aspIOCStr(iocbp->ioc_cmd), scb->loc_addr.socket,
414: aspStateStr(scb->state)));
415:
416: switch (iocbp->ioc_cmd) {
417: case ASPIOC_CloseSession:
418: if ((scb->state == ASPSTATE_Close) || (scb->rem_addr.node == 0))
419: break;
420:
421: Retry.retries = 3;
422: Retry.interval = 1;
423: aw.func = ASPFUNC_CloseSess;
424: aw.param1 = scb->sess_id;
425: aw.param2 = 0;
426: iocbp->ioc_private = (void *)scb;
427: scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
428: iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
429: asp_send_req(gref, mioc, &scb->rem_addr, &Retry, &aw,
430: 0, ASPSTATE_WaitingForCloseSessRsp, 0x01);
431: return 0;
432:
433: case ASPIOC_ClientBind:
434: /*
435: * open an ATP channel
436: */
437: if ((err = atp_open(gref, 0)) != 0) {
438: asp_iocnak(gref, mioc, err);
439: return 0;
440: }
441: scb->atp_state = (atp_state_t *)gref->info;
442: scb->atp_state->pid = scb->pid;
443: /*
444: * bind to any available socket
445: */
446: scb->dflag = 2;
447: sockSav = scb->dflag;
448: if ((sock_num = (at_socket)atp_bind(gref, 0, &sockSav)) == 0) {
449: scb->atp_state = (atp_state_t *)0;
450: atp_close(gref, 0);
451: gref->info = (void *)scb;
452: asp_iocnak(gref, mioc, EINVAL);
453: return 0;
454: }
455: gref->info = (void *)scb;
456: asp_dequeue_scb(scb);
457: scb->atp_state->dflag = scb->dflag;
458: scb->loc_addr.socket = sock_num;
459: asp_scbQ[sock_num] = scb;
460: asp_inpC[sock_num]++;
461: atp_pidM[sock_num] = 0;
462: break;
463:
464: case ASPIOC_ListenerBind:
465: /*
466: * open an ATP channel
467: */
468: if ((err = atp_open(gref, 0)) != 0) {
469: asp_iocnak(gref, mioc, err);
470: return 0;
471: }
472: scb->atp_state = (atp_state_t *)gref->info;
473: scb->atp_state->pid = scb->pid;
474: /*
475: * bind to any available socket
476: */
477: if ((sock_num = (at_socket)atp_bind(gref, 0, 0)) == 0) {
478: scb->atp_state = (atp_state_t *)0;
479: atp_close(gref, 0);
480: gref->info = (void *)scb;
481: asp_iocnak(gref, mioc, EINVAL);
482: return 0;
483: }
484: gref->info = (void *)scb;
485: asp_dequeue_scb(scb);
486: scb->atp_state->dflag = scb->dflag;
487: scb->loc_addr.socket = sock_num;
488: asp_scbQ[sock_num] = scb;
489: asp_inpC[sock_num]++;
490: if (gbuf_cont(mioc))
491: *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->loc_addr;
492: break;
493:
494: case ASPIOC_GetLocEntity:
495: if ((gbuf_cont(mioc) == 0) || (scb->atp_state == 0)) {
496: asp_iocnak(gref, mioc, EPROTO);
497: return 0;
498: }
499: *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->loc_addr;
500: break;
501:
502: case ASPIOC_GetRemEntity:
503: if ((gbuf_cont(mioc) == 0) || (scb->atp_state == 0)) {
504: asp_iocnak(gref, mioc, EPROTO);
505: return 0;
506: }
507: *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->rem_addr;
508: break;
509:
510: case ASPIOC_GetSession:
511: if ((mdata = gbuf_cont(mioc)) == 0) {
512: asp_iocnak(gref, mioc, EPROTO);
513: return 0;
514: }
515: addr = (at_inet_t *)gbuf_rptr(mdata);
516: scb->tickle_interval = (unsigned short)addr->node;
517: scb->session_timer = addr->net;
518: server_scb = asp_scbQ[addr->socket];
519: /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
520: if (server_scb == 0) {
521: asp_iocnak(gref, mioc, EPROTO);
522: return 0;
523: }
524: if (server_scb->sess_ioc == 0) {
525: asp_iocnak(gref, mioc, EPROTO);
526: return 0;
527: }
528:
529: /*
530: * open an ATP channel
531: */
532: if ((err = atp_open(gref, 0)) != 0) {
533: gref->info = (void *)scb;
534: asp_iocnak(gref, mioc, err);
535: return 0;
536: }
537: scb->atp_state = (atp_state_t *)gref->info;
538: scb->atp_state->pid = scb->pid;
539: /*
540: * bind to any available socket
541: */
542: scb->dflag = 3;
543: sockSav = scb->dflag;
544: if ((sock_num = (at_socket)atp_bind(gref, 0, &sockSav)) == 0) {
545: atp_close(gref, 0);
546: asp_dequeue_scb(scb);
547: ATDISABLE(s, aspall_lock);
548: sock_num = sockSav;
549: scb->loc_addr.socket = sock_num;
550: for (curr_scb = asp_scbQ[sock_num];
551: curr_scb->next_scb; curr_scb = curr_scb->next_scb) ;
552: scb->prev_scb = curr_scb;
553: curr_scb->next_scb = scb;
554: scb->atp_state = curr_scb->atp_state;
555: ATENABLE(s, aspall_lock);
556: } else {
557: asp_dequeue_scb(scb);
558: ATDISABLE(s, aspall_lock);
559: scb->loc_addr.socket = sock_num;
560: asp_scbQ[sock_num] = scb;
561: scb->atp_state->dflag = scb->dflag;
562: ATENABLE(s, aspall_lock);
563: }
564: gref->info = (void *)scb;
565: asp_inpC[sock_num]++;
566: gbuf_cont(mioc) = 0;
567: asp_accept(server_scb, scb, mdata);
568: break;
569:
570: case ASPIOC_GetStatus:
571: if ((mdata = gbuf_cont(mioc)) == 0) {
572: asp_iocnak(gref, mioc, EINVAL);
573: return 0;
574: }
575: gbuf_cont(mioc) = 0;
576: status_cmd = (asp_status_cmd_t *)gbuf_rptr(mdata);
577: aw.func = ASPFUNC_GetStatus;
578: aw.param1 = 0;
579: aw.param2 = 0;
580: scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
581: iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
582: asp_send_req(gref, mioc, &status_cmd->SLSEntityIdentifier,
583: &status_cmd->Retry, &aw, 1, ASPSTATE_WaitingForGetStatusRsp, 0xff);
584: gbuf_freeb(mdata);
585: return 0;
586:
587: case ASPIOC_OpenSession:
588: if ((mdata = gbuf_cont(mioc)) == 0) {
589: asp_iocnak(gref, mioc, EINVAL);
590: return 0;
591: }
592: gbuf_cont(mioc) = 0;
593: open_cmd = (asp_open_cmd_t *)gbuf_rptr(mdata);
594: scb->svc_addr = open_cmd->SLSEntityIdentifier;
595: scb->rem_addr = scb->svc_addr;
596: scb->rem_node = scb->rem_addr.node;
597: scb->rem_addr.node = 0;
598: scb->tickle_interval = open_cmd->TickleInterval;
599: scb->session_timer = open_cmd->SessionTimer;
600: aw.func = ASPFUNC_OpenSess;
601: aw.param1 = scb->loc_addr.socket;
602: aw.param2 = ASP_Version;
603: scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
604: iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
605: asp_send_req(gref, mioc, &open_cmd->SLSEntityIdentifier,
606: &open_cmd->Retry, &aw, 1, ASPSTATE_WaitingForOpenSessRsp, 0x01);
607: gbuf_freeb(mdata);
608: return 0;
609:
610: case ASPIOC_StatusBlock:
611: /*
612: * save the server status block
613: */
614: if (scb->stat_msg)
615: gbuf_freem(scb->stat_msg);
616: scb->stat_msg = gbuf_cont(mioc);
617: gbuf_cont(mioc) = 0;
618: break;
619:
620: /* *** Does scb->pid get used in a packet header,
621: and if so is it in ASP, or in ATP?
622: If not, do we need this call for anything?
623: (cap does currently use it in _ANS code.)
624: *** */
625: case ASPIOC_SetPid:
626: if (gbuf_cont(mioc) == 0) {
627: asp_iocnak(gref, mioc, EINVAL);
628: return 0;
629: }
630: scb->pid = *(int *)gbuf_rptr(gbuf_cont(mioc));
631: break;
632:
633: case ASPIOC_GetSessId:
634: if (gbuf_cont(mioc) == 0) {
635: asp_iocnak(gref, mioc, EINVAL);
636: return 0;
637: }
638: *(gref_t **)gbuf_rptr(gbuf_cont(mioc)) = gref;
639: break;
640:
641: case ASPIOC_EnableSelect:
642: #ifdef NOT_NEEDED_SELECT
643: scb->sel_on = 1;
644: if (scb->sess_ioc)
645: atalk_notify_sel(gref);
646: #endif
647: break;
648:
649: case ASPIOC_Look:
650: if (gbuf_cont(mioc) == 0) {
651: asp_iocnak(gref, mioc, EINVAL);
652: return 0;
653: }
654: if (scb->sess_ioc) {
655: primitives = (union asp_primitives *)gbuf_rptr(scb->sess_ioc);
656: if (primitives->Primitive == ASPFUNC_CmdReply)
657: *(int *)gbuf_rptr(gbuf_cont(mioc)) = 0;
658: else
659: *(int *)gbuf_rptr(gbuf_cont(mioc)) = 1;
660: } else
661: *(int *)gbuf_rptr(gbuf_cont(mioc)) = -1;
662: break;
663:
664: case DDP_IOC_GET_CFG:
665: {
666: struct atp_state *atp = (struct atp_state *)gref->info;
667: if (atp->dflag)
668: atp = atp->atp_msgq;
669:
670: if (gbuf_cont(mioc) == 0) {
671: asp_iocnak(gref, mioc, EINVAL);
672: return 0;
673: }
674: /* *** borrowed from ddp_proto.c to handle DDP_IOC_GET_CFG
675: on atp fd *** */
676: scb->state = ASPSTATE_Idle;
677: {
678: /* *** was ddp_get_cfg() *** */
679: ddp_addr_t *cfgp =
680: (ddp_addr_t *)gbuf_rptr(gbuf_cont(mioc));
681: cfgp->inet.net = ifID_home->ifThisNode.s_net;
682: cfgp->inet.node = ifID_home->ifThisNode.s_node;
683: cfgp->inet.socket = atp->atp_socket_no;
684: cfgp->ddptype = DDP_ATP;
685: }
686: gbuf_wset(gbuf_cont(mioc), sizeof(at_inet_t));
687: }
688: break;
689:
690: default:
691: asp_iocnak(gref, mioc, EINVAL);
692: return 0;
693: }
694:
695: asp_iocack(gref, mioc);
696: return 0;
697: } /* asp_wput */
698:
699: /*
700: * send request routine
701: */
702: StaticProc int
703: asp_send_req(gref, mioc, dest, retry, awp, xo, state, bitmap)
704: gref_t *gref;
705: gbuf_t *mioc;
706: at_inet_t *dest;
707: at_retry_t *retry;
708: asp_word_t *awp;
709: unsigned char xo;
710: unsigned char state;
711: unsigned char bitmap;
712: {
713: int i;
714: gbuf_t *mdata;
715: ioc_t *iocbp;
716: struct atp_set_default *sd;
717: at_ddp_t *ddp;
718: at_atp_t *atp;
719: struct atpBDS *atpBDS;
720: asp_scb_t *scb = (asp_scb_t *)gref->info;
721:
722: /*
723: * allocate an ATP buffer for the request
724: */
725: if ((gbuf_cont(mioc) = gbuf_alloc(aspCMDsize, PRI_MED)) == 0) {
726: if (awp->func == ASPFUNC_Tickle)
727: gbuf_freem(mioc);
728: else
729: asp_iocnak(gref, mioc, ENOBUFS);
730: dPrintf(D_M_ASP, D_L_WARNING,
731: ("asp_send_req: ENOBUFS, loc=%d\n", scb->loc_addr.socket));
732:
733: return -1;
734: }
735: mdata = gbuf_cont(mioc);
736: iocbp = (ioc_t *)gbuf_rptr(mioc);
737:
738: /*
739: * build the request
740: */
741: atpBDS = (struct atpBDS *)gbuf_rptr(mdata);
742: gbuf_wset(mdata,atpBDSsize);
743: for (i=0; i < ATP_TRESP_MAX; i++) {
744: *(unsigned long *)atpBDS[i].bdsBuffAddr = 1;
745: *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE;
746: }
747: sd = (struct atp_set_default *)gbuf_wptr(mdata);
748: gbuf_winc(mdata,sizeof(struct atp_set_default));
749: sd->def_retries = (retry->retries == -1) ?
750: ATP_INFINITE_RETRIES : retry->retries;
751: sd->def_rate = retry->interval*TICKS_PER_SEC;
752: sd->def_BDSlen = atpBDSsize;
753: ddp = (at_ddp_t *)gbuf_wptr(mdata);
754: NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
755: ddp->src_node = scb->loc_addr.node;
756: NET_ASSIGN(ddp->dst_net, dest->net);
757: ddp->dst_node = dest->node;
758: ddp->dst_socket = dest->socket;
759: UAS_ASSIGN(ddp->checksum, 0);
760: atp = ATP_ATP_HDR(gbuf_wptr(mdata));
761: atp->xo = xo;
762: atp->xo_relt = xo;
763: atp->bitmap = bitmap;
764: gbuf_winc(mdata,TOTAL_ATP_HDR_SIZE);
765: *(asp_word_t *)atp->user_bytes = *awp;
766: iocbp->ioc_count = gbuf_len(mdata);
767: iocbp->ioc_rval = 0;
768:
769: /*
770: * send the request
771: */
772: scb->state = state;
773: dPrintf(D_M_ASP, D_L_INFO,
774: ("asp_send_req: %s, loc=%d, rem= %d, len=%d, state=%s\n",
775: aspCmdStr(awp->func),
776: scb->loc_addr.socket, ddp->dst_socket, iocbp->ioc_count,
777: aspStateStr(scb->state)));
778:
779: atp_send_req(gref, mioc);
780: return 0;
781: }
782:
783: /*
784: * send tickle routine
785: */
786: StaticProc void
787: asp_send_tickle(scb)
788: asp_scb_t *scb;
789: {
790: gbuf_t *mioc;
791: at_retry_t retry;
792: asp_word_t aw;
793: at_inet_t *dest;
794:
795: /*
796: * make sure the connection is still there
797: */
798: if (scb->rem_addr.node == 0)
799: return;
800:
801: if ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0) {
802: dPrintf(D_M_ASP, D_L_WARNING,
803: ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
804: scb->loc_addr.socket,scb->rem_addr.socket));
805: timeout(asp_send_tickle, (void *)scb, 10);
806: return;
807: }
808: gbuf_wset(mioc,sizeof(ioc_t));
809: gbuf_set_type(mioc, MSG_IOCTL);
810:
811: dest = scb->svc_addr.node ?
812: (at_inet_t *)&scb->svc_addr : (at_inet_t *)&scb->rem_addr;
813: retry.interval = scb->tickle_interval;
814: retry.retries = -1;
815: retry.backoff = 1;
816: aw.func = ASPFUNC_Tickle;
817: aw.param1 = scb->sess_id;
818: aw.param2 = 0;
819: ((ioc_t *)gbuf_rptr(mioc))->ioc_cr = (void *)scb;
820: ((ioc_t *)gbuf_rptr(mioc))->ioc_cmd = AT_ATP_ISSUE_REQUEST_TICKLE;
821:
822: if (asp_send_req(scb->gref, mioc, dest, &retry, &aw, 0, scb->state, 0)) {
823: dPrintf(D_M_ASP, D_L_WARNING,
824: ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
825: scb->loc_addr.socket,scb->rem_addr.socket));
826:
827: timeout(asp_send_tickle, (void *)scb, 10);
828: return;
829: }
830: }
831:
832: /*
833: * accept connection routine
834: */
835: StaticProc void
836: asp_accept(scb, sess_scb, m)
837: asp_scb_t *scb;
838: asp_scb_t *sess_scb;
839: gbuf_t *m;
840: {
841: int s;
842: gbuf_t *mdata;
843: at_ddp_t *ddp;
844: at_atp_t *atp;
845: asp_word_t *awp;
846: at_inet_t rem_addr;
847:
848: mdata = scb->sess_ioc;
849: ddp = (at_ddp_t *)gbuf_rptr(mdata);
850: atp = (at_atp_t *)(gbuf_rptr(mdata) + DDP_X_HDR_SIZE);
851: rem_addr.net = NET_VALUE(ddp->src_net);
852: rem_addr.node = ddp->src_node;
853: rem_addr.socket = ddp->src_socket;
854: awp = (asp_word_t *)atp->user_bytes;
855:
856: sess_scb->loc_addr.net = NET_VALUE(ddp->dst_net);
857: sess_scb->loc_addr.node = ddp->dst_node;
858: NET_ASSIGN(ddp->src_net, sess_scb->loc_addr.net);
859: ddp->src_node = sess_scb->loc_addr.node;
860: NET_ASSIGN(ddp->dst_net, rem_addr.net);
861: ddp->dst_node = rem_addr.node;
862: ddp->dst_socket = rem_addr.socket;
863:
864: sess_scb->sess_id = sess_scb->loc_addr.socket;
865: sess_scb->rem_socket = rem_addr.socket;
866: sess_scb->rem_addr = rem_addr;
867: sess_scb->rem_addr.socket = awp->param1;
868: sess_scb->reply_socket = sess_scb->rem_addr.socket;
869: awp->func = sess_scb->loc_addr.socket;
870: awp->param1 = sess_scb->sess_id;
871: awp->param2 = 0;
872: gbuf_freeb(m);
873: ATDISABLE(s, scb->lock);
874: scb->sess_ioc = gbuf_next(mdata);
875: ATENABLE(s, scb->lock);
876: gbuf_next(mdata) = 0;
877: asp_timout(asp_hangup, sess_scb, sess_scb->session_timer);
878: atp_send_rsp(scb->gref, mdata, TRUE);
879: asp_send_tickle(sess_scb);
880: dPrintf(D_M_ASP, D_L_INFO,
881: ("asp_accept: ACCEPT connect request, loc=%d, rem=%x.%x.%d\n",
882: sess_scb->loc_addr.socket,
883: sess_scb->rem_addr.net,
884: sess_scb->rem_addr.node,sess_scb->rem_addr.socket));
885: } /* asp_accept */
886:
887: /*
888: * timer routine
889: */
890: void asp_clock(arg)
891: void *arg;
892: {
893: int s;
894: asp_scb_t *scb;
895: void (*tmo_func)();
896:
897: ATDISABLE(s, asptmo_lock);
898: if (scb_tmo_list)
899: scb_tmo_list->tmo_delta--;
900: while (((scb = scb_tmo_list) != 0) && (scb_tmo_list->tmo_delta == 0)) {
901: if ((scb_tmo_list = scb->next_tmo) != 0)
902: scb_tmo_list->prev_tmo = 0;
903: if ((tmo_func = scb->tmo_func) != 0) {
904: scb->tmo_func = 0;
905: ATENABLE(s, asptmo_lock);
906: (*tmo_func)(scb);
907: ATDISABLE(s, asptmo_lock);
908: }
909: }
910: ATENABLE(s, asptmo_lock);
911:
912: if (++scb_tmo_cnt == 0) scb_tmo_cnt++;
913: timeout(asp_clock, (void *)arg, (1<<SESS_TMO_RES)*TICKS_PER_SEC);
914: }
915:
916: /*
917: * ACK reply routine
918: */
919: void
920: asp_ack_reply(gref, mioc)
921: register gref_t *gref;
922: register gbuf_t *mioc;
923: {
924: int s;
925: int len, msize, nbds;
926: register gbuf_t *mdata, *m, *mx;
927: struct atpBDS *atpBDS;
928: at_ddp_t *ddp;
929: at_atp_t *atp;
930: register asp_scb_t *scb, *sess_scb;
931: register ioc_t *iocbp;
932: register asp_word_t *awp;
933: register asp_command_ind_t *command_ind;
934: register asp_cmdreply_ind_t *cmdreply_ind;
935: at_inet_t rem_addr;
936:
937: iocbp = (ioc_t *)gbuf_rptr(mioc);
938:
939: if (iocbp->ioc_cmd == AT_ATP_ISSUE_REQUEST_TICKLE) {
940: /*
941: * ignore the ack for the tickle request
942: */
943: scb = (asp_scb_t *)iocbp->ioc_cr;
944: scb->tickle_tid = (unsigned short)iocbp->ioc_rval;
945: gbuf_freem(mioc);
946: return;
947: }
948:
949: scb = (asp_scb_t *)gref->info;
950: if (scb == 0) {
951: gbuf_freem(mioc);
952: return;
953: }
954:
955: if (iocbp->ioc_cmd == AT_ATP_GET_POLL) {
956: /*
957: * if no data, just drop the request
958: */
959: if ((mdata = gbuf_cont(mioc)) == 0) {
960: gbuf_freeb(mioc);
961: return;
962: }
963:
964: gbuf_set_type(mioc, MSG_IOCTL);
965: ddp = (at_ddp_t *)gbuf_rptr(mdata);
966: gbuf_rinc(mdata,DDP_X_HDR_SIZE);
967: atp = (at_atp_t *)gbuf_rptr(mdata);
968: gbuf_rinc(mdata,ATP_HDR_SIZE);
969: rem_addr.net = NET_VALUE(ddp->src_net);
970: rem_addr.node = ddp->src_node;
971: rem_addr.socket = ddp->src_socket;
972: awp = (asp_word_t *)atp->user_bytes;
973:
974: if (scb->next_scb) {
975: /*
976: * find the responsible scb
977: */
978: if ((scb = asp_find_scb(scb->loc_addr.socket, &rem_addr)) == 0) {
979: gbuf_freem(mioc);
980: return;
981: }
982: }
983: dPrintf(D_M_ASP, D_L_INFO,
984: ("asp_ack_reply: %s, loc=%d, rem=%x.%x.%d\n",
985: aspCmdStr(awp->func),scb->loc_addr.socket,
986: NET_VALUE(ddp->src_net) ,ddp->src_node,ddp->src_socket));
987:
988: if (scb->rem_addr.node)
989: asp_untimout(asp_hangup, scb);
990:
991: switch (awp->func) {
992: case ASPFUNC_GetStatus:
993: /*
994: * ignore if this is not a server socket
995: */
996: mx = 0;
997: if ((scb->dflag != 1) || (scb->stat_msg
998: && ((mx = gbuf_dupb(scb->stat_msg)) == 0)))
999: break;
1000: gbuf_freeb(mioc);
1001:
1002: /*
1003: * send the status block
1004: */
1005: if (gbuf_cont(mdata)) {
1006: gbuf_freem(gbuf_cont(mdata));
1007: gbuf_cont(mdata) = 0;
1008: }
1009: gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1010: if ((m = gbuf_alloc( (TOTAL_ATP_HDR_SIZE+atpBDSsize), PRI_MED)) == 0) {
1011: gbuf_freem(mdata);
1012: gbuf_freeb(mx);
1013: goto l_done;
1014: }
1015: bcopy(gbuf_rptr(mdata), gbuf_rptr(m), TOTAL_ATP_HDR_SIZE);
1016: gbuf_freeb(mdata);
1017: mdata = m;
1018: ddp = (at_ddp_t *)gbuf_rptr(mdata);
1019: gbuf_wset(mdata,DDP_X_HDR_SIZE);
1020: atp = (at_atp_t *)gbuf_wptr(mdata);
1021: gbuf_winc(mdata,ATP_HDR_SIZE);
1022: awp = (asp_word_t *)atp->user_bytes;
1023: NET_NET(ddp->src_net, ddp->dst_net);
1024: ddp->src_node = ddp->dst_node;
1025: NET_ASSIGN(ddp->dst_net, rem_addr.net);
1026: ddp->dst_node = rem_addr.node;
1027: ddp->dst_socket = rem_addr.socket;
1028: UAS_ASSIGN(ddp->checksum, 0);
1029: atpBDS = (struct atpBDS *)gbuf_wptr(mdata);
1030: msize = mx ? gbuf_msgsize(mx) : 0;
1031: for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) {
1032: len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE;
1033: msize -= ATP_DATA_SIZE;
1034: *(long *)atpBDS[nbds].bdsUserData = 0;
1035: UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1);
1036: UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len);
1037: }
1038: UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds);
1039: gbuf_winc(mdata,atpBDSsize);
1040: gbuf_cont(mdata) = mx;
1041: atp_send_rsp(gref, mdata, FALSE);
1042: goto l_done;
1043:
1044: case ASPFUNC_OpenSess:
1045: /*
1046: * ignore if server is not ready
1047: */
1048: if ((scb->dflag != 1) || (scb->stat_msg == 0))
1049: break;
1050: gbuf_freeb(mioc);
1051:
1052: if (gbuf_cont(mdata)) {
1053: gbuf_freem(gbuf_cont(mdata));
1054: gbuf_cont(mdata) = 0;
1055: }
1056: gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1057: gbuf_wset(mdata,TOTAL_ATP_HDR_SIZE);
1058: if (awp->param2 != ASP_Version) {
1059: /*
1060: * bad version number, send the OpenSession response
1061: */
1062: awp->func = 0;
1063: awp->param1 = 0;
1064: awp->param2 = (unsigned short)ASPERR_BadVersNum;
1065: dPrintf(D_M_ASP, D_L_INFO,
1066: (" : version=%d\n",
1067: ASPERR_BadVersNum));
1068:
1069: NET_NET(ddp->src_net, ddp->dst_net);
1070: ddp->src_node = ddp->dst_node;
1071: NET_ASSIGN(ddp->dst_net, rem_addr.net);
1072: ddp->dst_node = rem_addr.node;
1073: ddp->dst_socket = rem_addr.socket;
1074: atp_send_rsp(gref, mdata, FALSE);
1075: return;
1076: }
1077:
1078: /*
1079: * queue the connection request
1080: */
1081: ATDISABLE(s, scb->lock);
1082: gbuf_next(mdata) = 0;
1083: if ((m = scb->sess_ioc) == 0) {
1084: scb->sess_ioc = mdata;
1085: if (scb->get_wait)
1086: thread_wakeup(&scb->event);
1087: else
1088: atalk_notify_sel(gref);
1089: } else {
1090: while (gbuf_next(m))
1091: m = gbuf_next(m);
1092: gbuf_next(m) = mdata;
1093: }
1094: ATENABLE(s, scb->lock);
1095: dPrintf(D_M_ASP, D_L_INFO,
1096: (" : QUEUE connect request\n"));
1097:
1098: return;
1099:
1100: case ASPFUNC_Command:
1101: case ASPFUNC_Write:
1102: if ( (scb->sess_id != awp->param1)
1103: || (scb->rcv_seq_num != awp->param2)
1104: || BAD_REMADDR(rem_addr) ) {
1105: char era[8], ra[8];
1106: sprintf(era,"%d.%d", scb->rem_addr.node,scb->rem_addr.socket);
1107: sprintf(ra,"%d.%d", rem_addr.node,rem_addr.socket);
1108: dPrintf(D_M_ASP, D_L_WARNING,
1109: (" : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
1110: scb->sess_id,scb->rcv_seq_num,awp->param2,era,ra));
1111: gbuf_cont(mioc) = 0;
1112: gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1113: atp_drop_req(gref, mdata);
1114: break;
1115: }
1116: scb->reply_socket = rem_addr.socket;
1117: if (awp->func == ASPFUNC_Write)
1118: scb->wrt_seq_num = scb->rcv_seq_num;
1119: NEXT_SEQ_NUM(scb->rcv_seq_num);
1120: gbuf_set_type(mioc, MSG_PROTO);
1121: gbuf_wset(mioc,sizeof(asp_command_ind_t));
1122: command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
1123: command_ind->Primitive = (int)awp->func;
1124: command_ind->ReqRefNum =
1125: *(unsigned short *)atp->tid;
1126: command_ind->ReqType = awp->func;
1127:
1128: mdata = gbuf_strip(mdata);
1129: gbuf_cont(mioc) = mdata;
1130: ATDISABLE(s, scb->lock);
1131: if (scb->req_flag) {
1132: if ((mx = scb->req_msgq) != 0) {
1133: while (gbuf_next(mx))
1134: mx = gbuf_next(mx);
1135: gbuf_next(mx) = mioc;
1136: } else
1137: scb->req_msgq = mioc;
1138: ATENABLE(s, scb->lock);
1139: } else {
1140: scb->req_flag = 1;
1141: ATENABLE(s, scb->lock);
1142: asp_putnext(scb->gref, mioc);
1143: }
1144: goto l_done;
1145:
1146: case ASPFUNC_WriteContinue:
1147: if ( (scb->sess_id != awp->param1)
1148: || (scb->snd_seq_num != awp->param2)
1149: || BAD_REMADDR(rem_addr) ) {
1150: break;
1151: }
1152: scb->reply_socket = rem_addr.socket;
1153: gbuf_set_type(mioc, MSG_PROTO);
1154: gbuf_wset(mioc,sizeof(asp_command_ind_t));
1155: command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
1156: command_ind->Primitive = (int)awp->func;
1157: command_ind->ReqRefNum =
1158: *(unsigned short *)atp->tid;
1159: command_ind->ReqType = awp->func;
1160:
1161: mdata = gbuf_strip(mdata);
1162: gbuf_cont(mioc) = mdata;
1163: asp_putnext(scb->gref, mioc);
1164: goto l_done;
1165:
1166: case ASPFUNC_Tickle:
1167: if (scb->stat_msg) {
1168: sess_scb = asp_scbQ[awp->param1];
1169: if (sess_scb && sess_scb->next_scb)
1170: sess_scb = asp_find_scb(
1171: sess_scb->loc_addr.socket, &rem_addr);
1172: if (sess_scb) {
1173: if (sess_scb->rem_addr.node)
1174: asp_untimout(asp_hangup, sess_scb);
1175: if (sess_scb->rem_addr.node)
1176: asp_timout(asp_hangup, sess_scb, sess_scb->session_timer);
1177: }
1178: }
1179: dPrintf(D_M_ASP, D_L_INFO,
1180: (" : Tickle, %d -> %d, id=%d\n",
1181: ddp->src_socket,ddp->dst_socket,awp->param1));
1182: break;
1183:
1184: case ASPFUNC_CloseSess:
1185: if ( (scb->sess_id != awp->param1)
1186: || (scb->state == ASPSTATE_Close)
1187: || (scb->state == ASPSTATE_WaitingForCloseSessRsp)
1188: || (scb->rem_addr.net != rem_addr.net)
1189: || (scb->rem_addr.node != rem_addr.node) ) {
1190: dPrintf(D_M_ASP, D_L_INFO,
1191: (" : CLOSE retry, loc=%d, rem=%x.%x.%d\n",
1192: scb->loc_addr.socket,
1193: scb->rem_addr.net,
1194: scb->rem_addr.node,
1195: scb->rem_addr.socket));
1196:
1197: break;
1198: }
1199: gbuf_freeb(mioc);
1200:
1201: /*
1202: * build the CloseSess response to be sent to peer
1203: * when the session is closed by the user.
1204: */
1205: if (gbuf_cont(mdata)) {
1206: gbuf_freem(gbuf_cont(mdata));
1207: gbuf_cont(mdata) = 0;
1208: }
1209: gbuf_rdec(mdata,TOTAL_ATP_HDR_SIZE);
1210: gbuf_wset(mdata,TOTAL_ATP_HDR_SIZE);
1211: NET_NET(ddp->src_net, ddp->dst_net);
1212: ddp->src_node = ddp->dst_node;
1213: NET_ASSIGN(ddp->dst_net, rem_addr.net);
1214: ddp->dst_node = rem_addr.node;
1215: ddp->dst_socket = rem_addr.socket;
1216: awp->func = 0;
1217: awp->param1 = 0;
1218: awp->param2 = 0;
1219: dPrintf(D_M_ASP,D_L_INFO,
1220: (" : CLOSE, loc=%d, rem=%x.%x.%d\n",
1221: scb->loc_addr.socket,
1222: scb->rem_addr.net,
1223: scb->rem_addr.node,
1224: scb->rem_addr.socket));
1225:
1226: gbuf_next(mdata) = 0;
1227: ATDISABLE(s, scb->lock);
1228: if (scb->sess_ioc)
1229: gbuf_freel(scb->sess_ioc);
1230: scb->sess_ioc = mdata;
1231: scb->state = ASPSTATE_Close;
1232: ATENABLE(s, scb->lock);
1233:
1234: /*
1235: * notify upstream of the CloseSess from peer
1236: */
1237: asp_hangup(scb);
1238: return;
1239:
1240: case ASPFUNC_Attention:
1241: if ( (scb->sess_id != awp->param1)
1242: || (scb->rem_addr.net != rem_addr.net)
1243: || (scb->rem_addr.node != rem_addr.node) ) {
1244: break;
1245: }
1246: gbuf_set_type(mioc, MSG_PROTO);
1247: gbuf_wset(mioc,sizeof(asp_command_ind_t));
1248: command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
1249: command_ind->Primitive = (int)awp->func;
1250: command_ind->ReqRefNum =
1251: *(unsigned short *)atp->tid;
1252: command_ind->ReqType = awp->func;
1253: scb->attn_tid = *(unsigned short *)atp->tid;
1254: scb->attn_flag = 1;
1255: gbuf_rdec(mdata,2); /* attention code */
1256:
1257: mdata = gbuf_strip(mdata);
1258: gbuf_cont(mioc) = mdata;
1259: asp_putnext(scb->gref, mioc);
1260: goto l_done;
1261:
1262: default:
1263: dPrintf(D_M_ASP, D_L_WARNING,
1264: (" : UNKNOWN func, func=%d\n",
1265: awp->func));
1266:
1267: break;
1268: }
1269: }
1270:
1271: else if (iocbp->ioc_cmd == AT_ATP_REQUEST_COMPLETE) {
1272: if (scb->next_scb) {
1273: /*
1274: * find the responsible scb
1275: */
1276: scb = (asp_scb_t *)iocbp->ioc_private;
1277: if ((scb == 0) || (scb->magic_num != 222)) {
1278: dPrintf(D_M_ASP, D_L_ERROR,
1279: ("asp_ack_reply: CAN'T find scb 1\n"));
1280: gbuf_freem(mioc);
1281: return;
1282: }
1283: }
1284: dPrintf(D_M_ASP, D_L_INFO,
1285: ("asp_ack_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1286: scb->loc_addr.socket,
1287: scb->rem_addr.net,
1288: scb->rem_addr.node,
1289: scb->rem_addr.socket,
1290: aspStateStr(scb->state)));
1291:
1292: switch (scb->state) {
1293: case ASPSTATE_Close:
1294: case ASPSTATE_Idle:
1295: scb->rem_addr.node = 0;
1296: gbuf_freem(mioc);
1297: ATDISABLE(s, scb->lock);
1298: if (scb->get_wait)
1299: thread_wakeup(&scb->event);
1300: else
1301: atalk_notify_sel(gref);
1302: ATENABLE(s, scb->lock);
1303: return;
1304:
1305: case ASPSTATE_WaitingForGetStatusRsp:
1306: scb->ioc_wait = 0;
1307: scb->state = ASPSTATE_Idle;
1308: mx = gbuf_cont(mioc);
1309: gbuf_cont(mioc) = 0;
1310: mdata = gbuf_cont(mx);
1311: gbuf_cont(mx) = 0;
1312: iocbp->ioc_cmd = ASPIOC_GetStatus;
1313: iocbp->ioc_count = 0;
1314: iocbp->ioc_rval = mdata ? gbuf_msgsize(mdata) : 0;
1315: gbuf_freeb(mx);
1316: atalk_putnext(gref, mioc);
1317: atalk_putnext(gref, mdata);
1318: return;
1319:
1320: case ASPSTATE_WaitingForOpenSessRsp:
1321: scb->ioc_wait = 0;
1322: scb->state = ASPSTATE_Idle;
1323: mx = gbuf_cont(mioc);
1324: gbuf_cont(mioc) = 0;
1325: if (gbuf_cont(mx)) {
1326: gbuf_freem(gbuf_cont(mx));
1327: gbuf_cont(mx) = 0;
1328: }
1329: iocbp->ioc_cmd = ASPIOC_OpenSession;
1330: iocbp->ioc_rval = 0;
1331: iocbp->ioc_count = 0;
1332: atpBDS = (struct atpBDS *)gbuf_rptr(mx);
1333: awp = (asp_word_t *)atpBDS->bdsUserData;
1334: if (awp->param2) {
1335: gbuf_freeb(mx);
1336: asp_iocnak(gref, mioc, ECONNREFUSED);
1337: } else {
1338: scb->rem_addr.node = scb->rem_node;
1339: scb->rem_addr.socket = awp->func;
1340: scb->sess_id = awp->param1;
1341: gbuf_freeb(mx);
1342: atalk_putnext(gref, mioc);
1343: asp_timout(asp_hangup, scb, scb->session_timer);
1344: asp_send_tickle(scb);
1345: dPrintf(D_M_ASP, D_L_INFO,
1346: ("asp_ack_reply: CONNECT, loc=%d, rem=%x.%x.%d\n",
1347: scb->loc_addr.socket,
1348: scb->rem_addr.net,
1349: scb->rem_addr.node,
1350: scb->rem_addr.socket));
1351: }
1352: return;
1353:
1354: case ASPSTATE_WaitingForCommandRsp:
1355: case ASPSTATE_WaitingForWriteRsp:
1356: case ASPSTATE_WaitingForWriteContinueRsp:
1357: if (scb->rem_addr.node)
1358: asp_untimout(asp_hangup, scb);
1359: NEXT_SEQ_NUM(scb->snd_seq_num);
1360: scb->state = ASPSTATE_Idle;
1361: gbuf_set_type(mioc, MSG_PROTO);
1362: mx = gbuf_cont(mioc);
1363: mdata = gbuf_cont(mx);
1364: gbuf_cont(mioc) = mdata;
1365: atpBDS = (struct atpBDS *)gbuf_rptr(mx);
1366: cmdreply_ind = (asp_cmdreply_ind_t *)gbuf_rptr(mioc);
1367: cmdreply_ind->Primitive = ASPFUNC_CmdReply;
1368: cmdreply_ind->CmdResult = *(int *)atpBDS->bdsUserData;
1369: gbuf_wset(mioc,sizeof(asp_cmdreply_ind_t));
1370: gbuf_freeb(mx);
1371: asp_putnext(scb->gref, mioc);
1372: goto l_done;
1373:
1374: case ASPSTATE_WaitingForCloseSessRsp:
1375: scb->ioc_wait = 0;
1376: scb->state = ASPSTATE_Close;
1377: scb->rem_addr.node = 0;
1378: iocbp->ioc_cmd = ASPIOC_CloseSession;
1379: iocbp->ioc_rval = 0;
1380: if (gbuf_cont(mioc)) {
1381: gbuf_freem(gbuf_cont(mioc));
1382: gbuf_cont(mioc) = 0;
1383: }
1384: atalk_putnext(scb->gref, mioc);
1385: atp_cancel_req(scb->gref, (unsigned int)scb->tickle_tid);
1386: scb->tickle_tid = 0;
1387: return;
1388:
1389: default:
1390: dPrintf(D_M_ASP, D_L_WARNING,
1391: (" : UNKNOWN state, state=%s\n",
1392: aspStateStr(scb->state)));
1393: break;
1394: }
1395: }
1396:
1397: else {
1398: if (scb->next_scb) {
1399: /*
1400: * find the responsible scb
1401: */
1402: scb = (asp_scb_t *)iocbp->ioc_cr;
1403: if ((scb == 0) || (scb->magic_num != 222)) {
1404: dPrintf(D_M_ASP, D_L_ERROR,
1405: ("asp_ack_reply: CAN'T find scb 2\n"));
1406: gbuf_freem(mioc);
1407: return;
1408: }
1409: }
1410:
1411: switch (scb->state) {
1412: case ASPSTATE_Close:
1413: scb->rem_addr.node = 0;
1414: break;
1415: }
1416: }
1417:
1418: if (mioc != 0)
1419: gbuf_freem(mioc);
1420:
1421: l_done:
1422: if (scb->rem_addr.node)
1423: asp_timout(asp_hangup, scb, scb->session_timer);
1424: } /* asp_ack_reply */
1425:
1426: /*
1427: * NAK reply routine
1428: */
1429: void
1430: asp_nak_reply(gref, mioc)
1431: register gref_t *gref;
1432: register gbuf_t *mioc;
1433: {
1434: register asp_scb_t *scb;
1435: register ioc_t *iocbp;
1436:
1437: iocbp = (ioc_t *)gbuf_rptr(mioc);
1438:
1439: if (iocbp->ioc_cmd == AT_ATP_ISSUE_REQUEST_TICKLE) {
1440: /*
1441: * no tickle, close session
1442: */
1443: scb = (asp_scb_t *)iocbp->ioc_cr;
1444: gbuf_freem(mioc);
1445: asp_hangup(scb);
1446: dPrintf(D_M_ASP, D_L_WARNING,
1447: ("tickle_nak: loc=%d, rem=%x.%x.%d, state=%s\n",
1448: scb->loc_addr.socket,
1449: scb->rem_addr.net,
1450: scb->rem_addr.node,
1451: scb->rem_addr.socket,
1452: aspStateStr(scb->state)));
1453:
1454: return;
1455: }
1456:
1457: scb = (asp_scb_t *)gref->info;
1458: if (scb == 0) {
1459: gbuf_freem(mioc);
1460: return;
1461: }
1462:
1463: if (iocbp->ioc_cmd == AT_ATP_REQUEST_COMPLETE) {
1464: if (scb->next_scb) {
1465: /*
1466: * find the responsible scb
1467: */
1468: scb = (asp_scb_t *)iocbp->ioc_private;
1469: if ((scb == 0) || (scb->magic_num != 222)) {
1470: dPrintf(D_M_ASP, D_L_ERROR,
1471: ("asp_nak_reply: CAN'T find scb 1\n"));
1472: gbuf_freem(mioc);
1473: return;
1474: }
1475: }
1476: dPrintf(D_M_ASP, D_L_WARNING,
1477: ("asp_nak_reply: RSP, loc=%d, rem=%x.%x.%d, state=%s\n",
1478: scb->loc_addr.socket,
1479: scb->rem_addr.net,
1480: scb->rem_addr.node,
1481: scb->rem_addr.socket,
1482: aspStateStr(scb->state)));
1483:
1484: switch (scb->state) {
1485: case ASPSTATE_WaitingForGetStatusRsp:
1486: iocbp->ioc_cmd = ASPIOC_GetStatus;
1487: break;
1488:
1489: case ASPSTATE_WaitingForOpenSessRsp:
1490: iocbp->ioc_cmd = ASPIOC_OpenSession;
1491: break;
1492:
1493: case ASPSTATE_WaitingForCommandRsp:
1494: case ASPSTATE_WaitingForWriteRsp:
1495: case ASPSTATE_WaitingForWriteContinueRsp:
1496: scb->state = ASPSTATE_Idle;
1497:
1498: /* last remaining use of MSG_ERROR */
1499: gbuf_set_type(mioc, MSG_ERROR);
1500: *gbuf_rptr(mioc) = (u_char)EPROTO;
1501: gbuf_wset(mioc, 1);
1502: if (gbuf_cont(mioc)) {
1503: gbuf_freem(gbuf_cont(mioc));
1504: gbuf_cont(mioc) = 0;
1505: }
1506:
1507: asp_putnext(scb->gref, mioc);
1508: return;
1509:
1510: case ASPSTATE_WaitingForCloseSessRsp:
1511: scb->state = ASPSTATE_Close;
1512: /* fall through */
1513: case ASPSTATE_Close: /* new for PR-2296832 */
1514: scb->rem_addr.node = 0;
1515: iocbp->ioc_cmd = ASPIOC_CloseSession;
1516: iocbp->ioc_rval = 0;
1517: if (gbuf_cont(mioc)) {
1518: gbuf_freem(gbuf_cont(mioc));
1519: gbuf_cont(mioc) = 0;
1520: }
1521: gbuf_set_type(mioc, MSG_IOCACK);
1522: atalk_putnext(scb->gref, mioc);
1523: return;
1524:
1525: default:
1526: gbuf_freem(mioc);
1527: return;
1528: }
1529: scb->state = ASPSTATE_Idle;
1530: atalk_putnext(gref, mioc);
1531: }
1532:
1533: else {
1534: if (scb->next_scb) {
1535: /*
1536: * find the responsible scb
1537: */
1538: scb = (asp_scb_t *)iocbp->ioc_cr;
1539: if ((scb == 0) || (scb->magic_num != 222)) {
1540: dPrintf(D_M_ASP, D_L_ERROR,
1541: ("asp_nak_reply: CAN'T find scb 2\n"));
1542: gbuf_freem(mioc);
1543: return;
1544: }
1545: }
1546:
1547: switch (scb->state) {
1548: case ASPSTATE_Close:
1549: scb->rem_addr.node = 0;
1550: break;
1551: }
1552:
1553: gbuf_freem(mioc);
1554: }
1555: } /* asp_nak_reply */
1556:
1557: /*
1558: * delete scb from the use list
1559: */
1560: StaticProc void
1561: asp_dequeue_scb(scb)
1562: asp_scb_t *scb;
1563: {
1564: int s;
1565:
1566: ATDISABLE(s, aspall_lock);
1567: if (scb == scb_used_list) {
1568: if ((scb_used_list = scb->next_scb) != 0)
1569: scb->next_scb->prev_scb = 0;
1570: } else {
1571: if ((scb->prev_scb->next_scb = scb->next_scb) != 0)
1572: scb->next_scb->prev_scb = scb->prev_scb;
1573: }
1574: ATENABLE(s, aspall_lock);
1575:
1576: scb->next_scb = 0;
1577: scb->prev_scb = 0;
1578: }
1579:
1580: /*
1581: * find scb routine
1582: */
1583: StaticProc asp_scb_t *
1584: asp_find_scb(sock_num, rem_addr)
1585: unsigned char sock_num;
1586: at_inet_t *rem_addr;
1587: {
1588: int s;
1589: asp_scb_t *scb;
1590: asp_scb_t *alt_scb = 0;
1591:
1592: ATDISABLE(s, aspall_lock);
1593: for (scb = asp_scbQ[sock_num]; scb; scb = scb->next_scb) {
1594: if ((scb->rem_addr.net == rem_addr->net)
1595: && (scb->rem_addr.node == rem_addr->node)) {
1596: if ((scb->rem_addr.socket == rem_addr->socket)
1597: || (scb->rem_socket == rem_addr->socket))
1598: break;
1599: else if (alt_scb == 0)
1600: alt_scb = scb;
1601: }
1602: }
1603:
1604: if ((scb == 0) && ((scb = alt_scb) == 0)) {
1605: dPrintf(D_M_ASP, D_L_ERROR,
1606: ("asp_find_scb: CAN'T find scb, loc=%d, rem=%x.%x.%d\n",
1607: sock_num,
1608: rem_addr->net,
1609: rem_addr->node,
1610: rem_addr->socket));
1611: }
1612: ATENABLE(s, aspall_lock);
1613:
1614: return scb;
1615: }
1616:
1617: /*
1618: * timout routine
1619: */
1620: StaticProc void
1621: asp_timout(func, scb, seconds)
1622: void (*func)();
1623: register asp_scb_t *scb;
1624: int seconds;
1625: {
1626: int s;
1627: unsigned char sum;
1628: register asp_scb_t *curr_scb, *prev_scb;
1629:
1630: if (scb->tmo_func)
1631: return;
1632:
1633: scb->tmo_func = func;
1634: scb->tmo_delta = (seconds>>SESS_TMO_RES);
1635: scb->tmo_cnt = scb_tmo_cnt;
1636:
1637: ATDISABLE(s, asptmo_lock);
1638: if (scb_tmo_list == 0) {
1639: scb->next_tmo = scb->prev_tmo = 0;
1640: scb_tmo_list = scb;
1641: ATENABLE(s, asptmo_lock);
1642: return;
1643: }
1644:
1645: prev_scb = 0;
1646: curr_scb = scb_tmo_list;
1647: sum = 0;
1648:
1649: while (1) {
1650: sum += curr_scb->tmo_delta;
1651: if (sum > scb->tmo_delta) {
1652: sum -= curr_scb->tmo_delta;
1653: scb->tmo_delta -= sum;
1654: curr_scb->tmo_delta -= scb->tmo_delta;
1655: break;
1656: }
1657: prev_scb = curr_scb;
1658: if ((curr_scb = curr_scb->next_tmo) == 0) {
1659: scb->tmo_delta -= sum;
1660: break;
1661: }
1662: }
1663:
1664: if (prev_scb) {
1665: scb->prev_tmo = prev_scb;
1666: if ((scb->next_tmo = prev_scb->next_tmo) != 0)
1667: prev_scb->next_tmo->prev_tmo = scb;
1668: prev_scb->next_tmo = scb;
1669: } else {
1670: scb->prev_tmo = 0;
1671: scb->next_tmo = scb_tmo_list;
1672: scb_tmo_list->prev_tmo = scb;
1673: scb_tmo_list = scb;
1674: }
1675: ATENABLE(s, asptmo_lock);
1676: }
1677:
1678: /*
1679: * untimout routine
1680: */
1681: StaticProc void
1682: asp_untimout(func, scb)
1683: void (*func)();
1684: register asp_scb_t *scb;
1685: {
1686: int s;
1687:
1688: if ((scb->tmo_cnt == scb_tmo_cnt) || (scb->tmo_func == 0))
1689: return;
1690:
1691: ATDISABLE(s, asptmo_lock);
1692: if (scb_tmo_list == scb) {
1693: if ((scb_tmo_list = scb->next_tmo) != 0) {
1694: scb_tmo_list->prev_tmo = 0;
1695: scb->next_tmo->tmo_delta += scb->tmo_delta;
1696: }
1697: } else if (scb->prev_tmo) {
1698: if ((scb->prev_tmo->next_tmo = scb->next_tmo) != 0) {
1699: scb->next_tmo->prev_tmo = scb->prev_tmo;
1700: scb->next_tmo->tmo_delta += scb->tmo_delta;
1701: }
1702: scb->prev_tmo = 0;
1703: }
1704: scb->tmo_func = 0;
1705: ATENABLE(s, asptmo_lock);
1706: }
1707:
1708: /*
1709: * hangup routine
1710: */
1711: StaticProc void
1712: asp_hangup(scb)
1713: asp_scb_t *scb;
1714: {
1715: int s;
1716:
1717: /*
1718: * set the state to Close
1719: */
1720: ATDISABLE(s, scb->lock);
1721: scb->state = ASPSTATE_Close;
1722: if (scb->tickle_tid) {
1723: atp_cancel_req(scb->gref, (unsigned int)scb->tickle_tid);
1724: scb->tickle_tid = 0;
1725: }
1726:
1727: /*
1728: * notify upstream of the hangup
1729: */
1730: if (scb->rem_addr.node) {
1731: if (scb->get_wait) {
1732: thread_wakeup(&scb->event);
1733: ATENABLE(s, scb->lock);
1734: } else {
1735: ATENABLE(s, scb->lock);
1736: atalk_notify_sel(scb->gref);
1737: }
1738: } else
1739: ATENABLE(s, scb->lock);
1740: }
1741:
1742: StaticProc void
1743: asp_iocack(gref, mioc)
1744: gref_t *gref;
1745: gbuf_t *mioc;
1746: {
1747: if (gbuf_cont(mioc))
1748: ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
1749: else
1750: ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
1751:
1752: gbuf_set_type(mioc, MSG_IOCACK);
1753: atalk_putnext(gref, mioc);
1754: }
1755:
1756: StaticProc void
1757: asp_iocnak(gref, mioc, err)
1758: gref_t *gref;
1759: gbuf_t *mioc;
1760: int err;
1761: {
1762: ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
1763: if (err == 0)
1764: err = ENXIO;
1765: ((ioc_t *)gbuf_rptr(mioc))->ioc_error = err;
1766: ((ioc_t *)gbuf_rptr(mioc))->ioc_rval = -1;
1767: if (gbuf_cont(mioc)) {
1768: gbuf_freem(gbuf_cont(mioc));
1769: gbuf_cont(mioc) = 0;
1770: }
1771:
1772: gbuf_set_type(mioc, MSG_IOCNAK);
1773: atalk_putnext(gref, mioc);
1774: }
1775:
1776: /*
1777: * the alloc scb routine
1778: */
1779: StaticProc asp_scb_t *
1780: asp_scb_alloc()
1781: {
1782: int s, i;
1783: gbuf_t *m;
1784: asp_scb_t *scb, *scb_array;
1785:
1786: ATDISABLE(s, aspall_lock);
1787: if (scb_free_list == 0) {
1788: if ((m = gbuf_alloc(SCBS_PER_BLK*sizeof(asp_scb_t), PRI_MED)) == 0)
1789: {
1790: ATENABLE(s, aspall_lock);
1791: return (asp_scb_t *)0;
1792: }
1793: bzero((char *)gbuf_rptr(m), SCBS_PER_BLK*sizeof(asp_scb_t));
1794: gbuf_cont(m) = scb_resource_m;
1795: scb_resource_m = m;
1796: scb_array = (asp_scb_t *)gbuf_rptr(m);
1797: for (i=0; i < SCBS_PER_BLK-1; i++)
1798: scb_array[i].next_scb = (asp_scb_t *)&scb_array[i+1];
1799: scb_array[i].next_scb = 0;
1800: scb_free_list = (asp_scb_t *)&scb_array[0];
1801: }
1802:
1803: scb = scb_free_list;
1804: scb_free_list = scb->next_scb;
1805: ATENABLE(s, aspall_lock);
1806: ATLOCKINIT(scb->lock);
1807: ATLOCKINIT(scb->delay_lock);
1808: ATEVENTINIT(scb->event);
1809: ATEVENTINIT(scb->delay_event);
1810:
1811: return scb;
1812: }
1813:
1814: /*
1815: * the free scb routine
1816: */
1817: StaticProc void
1818: asp_scb_free(scb)
1819: asp_scb_t *scb;
1820: {
1821: int s;
1822:
1823: bzero((char *)scb, sizeof(asp_scb_t));
1824: ATDISABLE(s, aspall_lock);
1825: scb->next_scb = scb_free_list;
1826: scb_free_list = scb;
1827: ATENABLE(s, aspall_lock);
1828: }
1829:
1830: /*
1831: * routine to pass up receive data
1832: */
1833: StaticProc void
1834: asp_putnext(gref, mproto)
1835: gref_t *gref;
1836: gbuf_t *mproto;
1837: {
1838: int s;
1839: gbuf_t *m;
1840: asp_scb_t *scb;
1841:
1842: scb = (asp_scb_t *)gref->info;
1843:
1844: /*
1845: * queue the message.
1846: */
1847: ATDISABLE(s, scb->lock);
1848: gbuf_next(mproto) = 0;
1849: if ((m = scb->sess_ioc) == 0)
1850: scb->sess_ioc = mproto;
1851: else {
1852: while (gbuf_next(m))
1853: m = gbuf_next(m);
1854: gbuf_next(m) = mproto;
1855: }
1856: scb->rcv_cnt++;
1857: if (scb->rcv_cnt >= MAX_RCV_CNT)
1858: scb->snd_stop = 1;
1859:
1860: if (scb->get_wait) {
1861: thread_wakeup(&scb->event);
1862: ATENABLE(s, scb->lock);
1863: } else if (mproto == scb->sess_ioc) {
1864: ATENABLE(s, scb->lock);
1865: atalk_notify_sel(gref);
1866: } else
1867: ATENABLE(s, scb->lock);
1868: } /* asp_putnext */
1869:
1870: /*
1871: * The following two routines are direct entries from system
1872: * calls to allow fast sending and recving of ASP data.
1873: */
1874:
1875: /* in ASPputmsg we expect:
1876:
1877: ASPFUNC_CmdReply
1878: ASPFUNC_Attention
1879: ASPFUNC_Command
1880: ASPFUNC_Write
1881: ASPFUNC_WriteContinue
1882: */
1883:
1884: int ASPputmsg(gref, ctlptr, datptr, flags, errp)
1885: gref_t *gref;
1886: strbuf_t *ctlptr;
1887: strbuf_t *datptr;
1888: int flags;
1889: int *errp;
1890: {
1891: int s, i, err, len;
1892: gbuf_t *mioc, *mdata, *mx;
1893: ioc_t *iocbp;
1894: strbuf_t ctlbuf;
1895: strbuf_t datbuf;
1896: asp_scb_t *scb;
1897: int nbds, result, msize, Primitive;
1898: unsigned char *wptr;
1899: struct atp_set_default *sd;
1900: at_ddp_t *ddp;
1901: at_atp_t *atp;
1902: struct atpBDS *atpBDS;
1903: asp_word_t *awp;
1904: union asp_primitives *primitives;
1905: unsigned short tid;
1906:
1907: if ((scb = (asp_scb_t *)gref->info) == 0) {
1908: dPrintf(D_M_ASP, D_L_ERROR,
1909: ("ASPputmsg: stale handle=0x%x, pid=%d\n",
1910: (u_int) gref, gref->pid));
1911:
1912: *errp = EINVAL;
1913: return -1;
1914: }
1915:
1916: if (scb->state == ASPSTATE_Close)
1917: return 0;
1918: if (scb->snd_stop) {
1919: *errp = EAGAIN;
1920: return -1;
1921: }
1922:
1923: /*
1924: * copy in the control and data info
1925: */
1926: if ((err = copyin((caddr_t)ctlptr,
1927: (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
1928: goto l_err;
1929: if ((err = copyin((caddr_t)datptr,
1930: (caddr_t)&datbuf, sizeof(datbuf))) != 0)
1931: goto l_err;
1932:
1933: /*
1934: * allocate buffer and copy in the control content
1935: */
1936: if (!(mioc = gbuf_alloc_wait(ctlbuf.len, TRUE))) {
1937: /* error return should not be possible */
1938: err = ENOBUFS;
1939: goto l_err;
1940: }
1941: gbuf_set_type(mioc, MSG_IOCTL); /* for later, in ATP */
1942: gbuf_wset(mioc, ctlbuf.len);
1943: if ((err = copyin((caddr_t)ctlbuf.buf,
1944: (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) {
1945: gbuf_freem(mioc);
1946: goto l_err;
1947: }
1948:
1949: iocbp = (ioc_t *)gbuf_rptr(mioc);
1950: primitives = (union asp_primitives *)gbuf_rptr(mioc);
1951: Primitive = primitives->Primitive;
1952: dPrintf(D_M_ASP, D_L_INFO,
1953: ("ASPputmsg: %s\n", aspCmdStr(Primitive)));
1954:
1955: /*
1956: * allocate buffer and copy in the data content
1957: */
1958: len = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize;
1959: if (!(mdata = gbuf_alloc_wait(datbuf.len+len, TRUE))) {
1960: /* error return should not be possible */
1961: err = ENOBUFS;
1962: gbuf_freem(mioc);
1963: goto l_err;
1964: }
1965: gbuf_wset(mdata,(datbuf.len+len));
1966: gbuf_cont(mioc) = mdata;
1967: if ((err = copyin((caddr_t)datbuf.buf,
1968: (caddr_t)(gbuf_rptr(mdata)+len), datbuf.len)) != 0) {
1969: gbuf_freem(mioc);
1970: goto l_err;
1971: }
1972:
1973: switch (Primitive) {
1974:
1975: case ASPFUNC_Command:
1976: case ASPFUNC_Write:
1977: case ASPFUNC_WriteContinue:
1978: case ASPFUNC_Attention:
1979: /*
1980: * build the command/write/write_continue request
1981: */
1982: wptr = gbuf_rptr(mdata);
1983: atpBDS = (struct atpBDS *)wptr;
1984: wptr += atpBDSsize;
1985: for (i=0; i < ATP_TRESP_MAX; i++) {
1986: *(unsigned long *)atpBDS[i].bdsBuffAddr = 1;
1987: *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE;
1988: }
1989: sd = (struct atp_set_default *)wptr;
1990: wptr += sizeof(struct atp_set_default);
1991: sd->def_retries = (scb->cmd_retry.retries == -1) ?
1992: ATP_INFINITE_RETRIES : scb->cmd_retry.retries;
1993: sd->def_rate = scb->cmd_retry.interval*TICKS_PER_SEC;
1994: sd->def_BDSlen = atpBDSsize;
1995: ddp = (at_ddp_t *)wptr;
1996: NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
1997: ddp->src_node = scb->loc_addr.node;
1998: NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
1999: ddp->dst_node = scb->rem_addr.node;
2000: ddp->dst_socket = scb->rem_addr.socket;
2001: UAS_ASSIGN(ddp->checksum, 0);
2002: atp = ATP_ATP_HDR(wptr);
2003: wptr += TOTAL_ATP_HDR_SIZE;
2004: atp->xo = 1;
2005: atp->xo_relt = 1;
2006: atp->bitmap = 0xff;
2007: awp = (asp_word_t *)atp->user_bytes;
2008: awp->func = (unsigned char)Primitive;
2009: awp->param1 = scb->sess_id;
2010: awp->param2 = scb->snd_seq_num;
2011: iocbp->ioc_private = (void *)scb;
2012: iocbp->ioc_count = gbuf_len(mdata);
2013: iocbp->ioc_rval = 0;
2014: iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
2015:
2016: /*
2017: * send the command/write/write_continue/attention request
2018: */
2019: ATDISABLE(s, scb->lock);
2020: switch (awp->func) {
2021: case ASPFUNC_Command:
2022: scb->state = ASPSTATE_WaitingForCommandRsp;
2023: break;
2024: case ASPFUNC_Write:
2025: scb->state = ASPSTATE_WaitingForWriteRsp;
2026: break;
2027: case ASPFUNC_WriteContinue:
2028: scb->state = ASPSTATE_WaitingForWriteContinueRsp;
2029: awp->param2 = scb->wrt_seq_num;
2030: break;
2031: case ASPFUNC_Attention:
2032: scb->state = ASPSTATE_WaitingForCommandRsp;
2033: atp->xo = 0;
2034: atp->xo_relt = 0;
2035: atp->bitmap = 0x01;
2036: gbuf_wdec(mdata,2);
2037: awp->param2 = *(unsigned short *)gbuf_wptr(mdata);
2038: break;
2039: }
2040: ATENABLE(s, scb->lock);
2041: dPrintf(D_M_ASP,D_L_INFO,
2042: ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
2043: (awp->func == ASPFUNC_Command ? "CommandReq" :
2044: awp->func == ASPFUNC_Write ? "WriteReq" :
2045: awp->func == ASPFUNC_WriteContinue ? "WriteContinue" :
2046: "AttentionReq"),scb->loc_addr.socket,
2047: NET_VALUE(ddp->dst_net),ddp->dst_node,ddp->dst_socket));
2048: atp_send_req(gref, mioc);
2049: return 0;
2050:
2051: case ASPFUNC_CmdReply:
2052:
2053: ATDISABLE(s, scb->lock);
2054: if (scb->req_msgq) {
2055: mx = scb->req_msgq;
2056: scb->req_msgq = gbuf_next(mx);
2057: gbuf_next(mx) = 0;
2058: ATENABLE(s, scb->lock);
2059: asp_putnext(scb->gref, mx);
2060: } else {
2061: scb->req_flag = 0;
2062: ATENABLE(s, scb->lock);
2063: }
2064: result = primitives->CmdReplyReq.CmdResult;
2065: tid = primitives->CmdReplyReq.ReqRefNum;
2066:
2067: /* Re-use the original mioc mbuf to send the response. */
2068: gbuf_rinc(mioc,sizeof(void *));
2069: gbuf_wset(mioc,0);
2070: ddp = (at_ddp_t *)gbuf_wptr(mioc);
2071: gbuf_winc(mioc,DDP_X_HDR_SIZE);
2072: atp = (at_atp_t *)gbuf_wptr(mioc);
2073: gbuf_winc(mioc,ATP_HDR_SIZE);
2074: NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
2075: ddp->src_node = scb->loc_addr.node;
2076: NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
2077: ddp->dst_node = scb->rem_addr.node;
2078: ddp->dst_socket = scb->reply_socket;
2079: ddp->type = DDP_ATP;
2080: UAS_ASSIGN(ddp->checksum, 0);
2081: UAS_ASSIGN(atp->tid, tid);
2082: if (scb->attn_flag && (tid == scb->attn_tid)) {
2083: scb->attn_flag = 0;
2084: atp->xo = 0;
2085: atp->xo_relt = 0;
2086: } else {
2087: atp->xo = 1;
2088: atp->xo_relt = 1;
2089: }
2090: atpBDS = (struct atpBDS *)gbuf_wptr(mioc);
2091: msize = mdata ? gbuf_msgsize(mdata) : 0;
2092: for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) {
2093: len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE;
2094: msize -= ATP_DATA_SIZE;
2095: *(long *)atpBDS[nbds].bdsUserData = 0;
2096: UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1);
2097: UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len);
2098: }
2099: UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds);
2100: *(long *)atpBDS[0].bdsUserData = (long)result;
2101: *(long *)atp->user_bytes = (long)result;
2102: gbuf_winc(mioc,atpBDSsize);
2103: dPrintf(D_M_ASP, D_L_INFO,
2104: ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
2105: scb->loc_addr.socket, aspStateStr(scb->state),
2106: (mdata ? gbuf_msgsize(mdata) : 0), result, tid));
2107: atp_send_rsp(gref, mioc, TRUE);
2108: return 0;
2109: }
2110:
2111: /* Not an expected ASPFUNC */
2112: gbuf_freem(mioc);
2113: err = EOPNOTSUPP;
2114:
2115: l_err:
2116: *errp = err;
2117: return -1;
2118: } /* ASPputmsg */
2119:
2120: int
2121: ASPgetmsg(gref, ctlptr, datptr, flags, errp)
2122: gref_t *gref;
2123: strbuf_t *ctlptr;
2124: strbuf_t *datptr;
2125: int *flags;
2126: int *errp;
2127: {
2128: int err, s, len, sum, rval;
2129: gbuf_t *mproto, *mdata;
2130: strbuf_t ctlbuf;
2131: strbuf_t datbuf;
2132: asp_scb_t *scb;
2133: unsigned char get_wait;
2134:
2135: if ((scb = (asp_scb_t *)gref->info) == 0) {
2136: dPrintf(D_M_ASP, D_L_ERROR,
2137: ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
2138: (u_int) gref, gref->pid));
2139:
2140: *errp = EINVAL;
2141: return -1;
2142: }
2143:
2144: ATDISABLE(s, scb->lock);
2145: if (scb->state == ASPSTATE_Close) {
2146: ATENABLE(s, scb->lock);
2147: return 0;
2148: }
2149:
2150: /*
2151: * get receive data
2152: */
2153: while ((mproto = scb->sess_ioc) == 0) {
2154: scb->get_wait = 1;
2155: err = tsleep(&scb->event, PSOCK | PCATCH, "aspgetmsg", 0);
2156: if (err != 0) {
2157: scb->get_wait = 0;
2158: ATENABLE(s, scb->lock);
2159: *errp = err;
2160: return -1;
2161: }
2162: if (scb->state == ASPSTATE_Close) {
2163: scb->get_wait = 0;
2164: ATENABLE(s, scb->lock);
2165: return 0;
2166: }
2167: }
2168: get_wait = scb->get_wait;
2169: scb->get_wait = 0;
2170: if ((ctlptr == 0) && (datptr == 0)) {
2171: ATENABLE(s, scb->lock);
2172: return 0;
2173: }
2174: scb->sess_ioc = gbuf_next(mproto);
2175: mdata = gbuf_cont(mproto);
2176: ATENABLE(s, scb->lock);
2177:
2178: /* last remaining use of MSG_ERROR */
2179: if (gbuf_type(mproto) == MSG_ERROR) {
2180: err = (int)gbuf_rptr(mproto)[0];
2181: goto l_err;
2182: }
2183:
2184: /*
2185: * copy in the control and data info
2186: */
2187: if ((err = copyin((caddr_t)ctlptr,
2188: (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
2189: goto l_err;
2190: if ((err = copyin((caddr_t)datptr,
2191: (caddr_t)&datbuf, sizeof(datbuf))) != 0)
2192: goto l_err;
2193: if ((datbuf.maxlen < 0) || (datbuf.maxlen < gbuf_msgsize(mdata))) {
2194: ATDISABLE(s, scb->lock);
2195: gbuf_next(mproto) = scb->sess_ioc;
2196: scb->sess_ioc = mproto;
2197: ATENABLE(s, scb->lock);
2198: return MOREDATA;
2199: }
2200:
2201: if (get_wait == 0) {
2202: /*
2203: * this is a hack to support the select() call.
2204: * we're not supposed to dequeue messages in the Streams
2205: * head's read queue this way; but there is no better way.
2206: */
2207: ATDISABLE(s, scb->lock);
2208: if (scb->sess_ioc == 0) {
2209: ATENABLE(s, scb->lock);
2210: } else {
2211: ATENABLE(s, scb->lock);
2212: atalk_notify_sel(gref);
2213: }
2214: }
2215:
2216: /*
2217: * copy out the control content and info
2218: */
2219: ctlbuf.len = gbuf_len(mproto);
2220: if ((err = copyout((caddr_t)gbuf_rptr(mproto),
2221: (caddr_t)ctlbuf.buf, ctlbuf.len)) != 0)
2222: goto l_err;
2223: if ((err = copyout((caddr_t)&ctlbuf,
2224: (caddr_t)ctlptr, sizeof(ctlbuf))) != 0)
2225: goto l_err;
2226:
2227: /*
2228: * copy out the data content and info
2229: */
2230: for (rval=0, sum=0; mdata && (rval == 0); mdata = gbuf_cont(mdata)) {
2231: len = gbuf_len(mdata);
2232: if (len) {
2233: if ((len + sum) > datbuf.maxlen) {
2234: len = datbuf.maxlen - sum;
2235: rval = MOREDATA;
2236: }
2237: if ((err = copyout((caddr_t)gbuf_rptr(mdata),
2238: (caddr_t)&datbuf.buf[sum], len)) != 0)
2239: goto l_err;
2240: sum += len;
2241: }
2242: }
2243: datbuf.len = sum;
2244: if ((err = copyout((caddr_t)&datbuf,
2245: (caddr_t)datptr, sizeof(datbuf))) != 0)
2246: goto l_err;
2247:
2248: #ifdef APPLETALK_DEBUG
2249: if (mproto == 0)
2250: kprintf("ASPgetmsg: null mproto!!!\n");
2251: #endif
2252:
2253: gbuf_freem(mproto);
2254:
2255: ATDISABLE(s, scb->lock);
2256: if (scb->sess_ioc)
2257: scb->rcv_cnt--;
2258: else {
2259: scb->rcv_cnt = 0;
2260: scb->snd_stop = 0;
2261: }
2262: ATENABLE(s, scb->lock);
2263: return rval;
2264:
2265: l_err:
2266: dPrintf(D_M_ASP, D_L_ERROR,
2267: ("ASPgetmsg: err=%d, loc=%d, rem=%x.%x.%d, state=%s\n",
2268: err, scb->loc_addr.socket,
2269: scb->rem_addr.net,
2270: scb->rem_addr.node, scb->rem_addr.socket,
2271: aspStateStr(scb->state)));
2272: ATDISABLE(s, scb->lock);
2273: gbuf_next(mproto) = scb->sess_ioc;
2274: scb->sess_ioc = mproto;
2275: ATENABLE(s, scb->lock);
2276: *errp = err;
2277: return -1;
2278: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.