|
|
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.