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