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