1: #if !defined(lint) && defined(DOSCCS) 2: static char sccsid[] = "@(#)pk0.c 5.7.1 (2.11BSD) 1997/10/2"; 3: #endif 4: 5: #include "uucp.h" 6: #include "pk.h" 7: 8: /* 9: * packet driver 10: */ 11: 12: char next[8] = { 1, 2, 3, 4, 5, 6, 7, 0}; /* packet sequence numbers */ 13: char mask[8] = { 1, 2, 4, 010, 020, 040, 0100, 0200 }; 14: 15: struct pack *pklines[NPLINES]; 16: 17: int Reacks; 18: 19: #define PKRTIME 4 20: #define PKWTIME 4 21: #define PKRSKEW 3 22: #define PKWSKEW 2 23: extern int pktimeout, pktimeskew, Ntimeout; 24: 25: /* 26: * receive control messages 27: */ 28: pkcntl(c, pk) 29: register struct pack *pk; 30: { 31: register cntl, val; 32: 33: val = c & MOD8; 34: cntl = (c>>3) & MOD8; 35: 36: if (!ISCNTL(c)) { 37: logent("PK0", "not cntl"); 38: return; 39: } 40: 41: switch(cntl) { 42: case INITB: 43: val++; 44: pk->p_xsize = pksizes[val]; 45: pk->p_lpsize = val; 46: pk->p_bits = 1; 47: if (pk->p_state & LIVE) { 48: pk->p_msg |= M_INITC; 49: break; 50: } 51: pk->p_state |= INITb; 52: if ((pk->p_state & INITa)==0) { 53: break; 54: } 55: pk->p_rmsg &= ~M_INITA; 56: pk->p_msg |= M_INITC; 57: break; 58: 59: case INITC: 60: if ((pk->p_state&INITab)==INITab) { 61: pk->p_state = LIVE; 62: pk->p_rmsg &= ~M_INITB; 63: } else 64: pk->p_msg |= M_INITB; 65: if (val) 66: pk->p_swindow = val; 67: break; 68: case INITA: 69: if (val == 0 && pk->p_state&LIVE) { 70: logent("PK0", "alloc change not implemented"); 71: break; 72: } 73: if (val) { 74: pk->p_state |= INITa; 75: pk->p_msg |= M_INITB; 76: pk->p_rmsg |= M_INITB; 77: pk->p_swindow = val; 78: } 79: break; 80: case RJ: 81: pk->p_state |= RXMIT; 82: pk->p_msg |= M_RR; 83: pk->p_rpr = val; 84: (void) pksack(pk); 85: break; 86: case RR: 87: pk->p_rpr = val; 88: if (pk->p_rpr == pk->p_ps) { 89: DEBUG(9, "Reack count is %d\n", ++Reacks); 90: if (Reacks >= 4) { 91: DEBUG(6, "Reack overflow on %d\n", val); 92: pk->p_state |= RXMIT; 93: pk->p_msg |= M_RR; 94: Reacks = 0; 95: } 96: } else { 97: Reacks = 0; 98: (void) pksack(pk); 99: } 100: break; 101: case SRJ: 102: logent("PK0", "srj not implemented"); 103: break; 104: case CLOSE: 105: pk->p_state = DOWN+RCLOSE; 106: return; 107: } 108: if (pk->p_msg) 109: pkoutput(pk); 110: } 111: 112: pkaccept(pk) 113: register struct pack *pk; 114: { 115: register x, seq; 116: char m, cntl, *p, imask, **bp; 117: int bad, accept, skip, t, cc; 118: unsigned short sum; 119: 120: bad = accept = skip = 0; 121: /* 122: * wait for input 123: */ 124: x = next[pk->p_pr]; 125: while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) { 126: pkgetpack(pk); 127: } 128: pk->p_imap = 0; 129: 130: /* 131: * determine input window in m. 132: */ 133: t = (~(-1<<(int)(pk->p_rwindow))) <<x; 134: m = t; 135: m |= t>>8; 136: 137: /* 138: * mark newly accepted input buffers 139: */ 140: for(x=0; x<8; x++) { 141: if ((imask & mask[x]) == 0) 142: continue; 143: 144: if (((cntl=pk->p_is[x])&0200) == 0) { 145: bad++; 146: free: 147: bp = (char **)pk->p_ib[x]; 148: *bp = (char *)pk->p_ipool; 149: pk->p_ipool = bp; 150: pk->p_is[x] = 0; 151: continue; 152: } 153: 154: pk->p_is[x] = ~(B_COPY+B_MARK); 155: sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377); 156: sum += pk->p_isum[x]; 157: if (sum == CHECK) { 158: seq = (cntl>>3) & MOD8; 159: if (m & mask[seq]) { 160: if (pk->p_is[seq] & (B_COPY | B_MARK)) { 161: dup: 162: pk->p_msg |= M_RR; 163: skip++; 164: goto free; 165: } 166: if (x != seq) { 167: p = pk->p_ib[x]; 168: pk->p_ib[x] = pk->p_ib[seq]; 169: pk->p_is[x] = pk->p_is[seq]; 170: pk->p_ib[seq] = p; 171: } 172: pk->p_is[seq] = B_MARK; 173: accept++; 174: cc = 0; 175: if (cntl&B_SHORT) { 176: pk->p_is[seq] = B_MARK+B_SHORT; 177: p = pk->p_ib[seq]; 178: cc = (unsigned)*p++ & 0377; 179: if (cc & 0200) { 180: cc &= 0177; 181: cc |= *p << 7; 182: } 183: } 184: pk->p_isum[seq] = pk->p_rsize - cc; 185: } else { 186: goto dup; 187: } 188: } else { 189: bad++; 190: goto free; 191: } 192: } 193: 194: /* 195: * scan window again turning marked buffers into 196: * COPY buffers and looking for missing sequence 197: * numbers. 198: */ 199: accept = 0; 200: t = -1; 201: for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) { 202: if (pk->p_is[x] & B_MARK) 203: pk->p_is[x] |= B_COPY; 204: 205: if (pk->p_is[x] & B_COPY) { 206: if (t >= 0) { 207: bp = (char **)pk->p_ib[x]; 208: *bp = (char *)pk->p_ipool; 209: pk->p_ipool = bp; 210: pk->p_is[x] = 0; 211: skip++; 212: } else 213: accept++; 214: } else { 215: if (t<0) 216: t = x; 217: } 218: } 219: 220: if (bad) { 221: pk->p_msg |= M_RJ; 222: } 223: 224: if (skip) { 225: pk->p_msg |= M_RR; 226: } 227: 228: pk->p_rcount = accept; 229: return accept; 230: } 231: 232: /*ARGSUSED*/ 233: pkread(pk, ibuf, icount) 234: register struct pack *pk; 235: char *ibuf; 236: int icount; 237: { 238: register x; 239: int is, cc, xfr, count; 240: char *cp, **bp; 241: 242: xfr = 0; 243: count = 0; 244: pktimeout = PKRTIME; 245: pktimeskew = PKRSKEW; 246: Ntimeout = 0; 247: while (pkaccept(pk) == 0) 248: ; 249: 250: while (icount) { 251: x = next[pk->p_pr]; 252: is = pk->p_is[x]; 253: 254: if (is & B_COPY) { 255: cc = MIN(pk->p_isum[x], icount); 256: if (cc==0 && xfr) { 257: break; 258: } 259: if (is & B_RESID) 260: cp = pk->p_rptr; 261: else { 262: cp = pk->p_ib[x]; 263: if (is & B_SHORT) { 264: if (*cp++ & 0200) 265: cp++; 266: } 267: } 268: pkmove(cp, ibuf, cc, B_READ); 269: ibuf += cc; 270: icount -= cc; 271: count += cc; 272: xfr++; 273: pk->p_isum[x] -= cc; 274: if (pk->p_isum[x] == 0) { 275: pk->p_pr = x; 276: bp = (char **)pk->p_ib[x]; 277: *bp = (char *)pk->p_ipool; 278: pk->p_ipool = bp; 279: pk->p_is[x] = 0; 280: pk->p_rcount--; 281: pk->p_msg |= M_RR; 282: } else { 283: pk->p_rptr = cp+cc; 284: pk->p_is[x] |= B_RESID; 285: } 286: if (cc==0) 287: break; 288: } else 289: break; 290: } 291: pkoutput(pk); 292: return count; 293: } 294: 295: /*ARGSUSED*/ 296: pkwrite(pk, ibuf, icount) 297: register struct pack *pk; 298: char *ibuf; 299: int icount; 300: { 301: register x; 302: int partial; 303: caddr_t cp; 304: int cc, fc, count; 305: 306: if (pk->p_state&DOWN || !pk->p_state&LIVE) { 307: return -1; 308: } 309: 310: pktimeout = PKWTIME; 311: pktimeskew = PKWSKEW; 312: Ntimeout = 0; 313: count = icount; 314: do { 315: while (pk->p_xcount>=pk->p_swindow) { 316: pkoutput(pk); 317: pkgetpack(pk); 318: } 319: x = next[pk->p_pscopy]; 320: while (pk->p_os[x]!=B_NULL) { 321: pkgetpack(pk); 322: } 323: pk->p_os[x] = B_MARK; 324: pk->p_pscopy = x; 325: pk->p_xcount++; 326: 327: cp = pk->p_ob[x] = (char *)malloc((unsigned)pk->p_xsize); 328: partial = 0; 329: if ((int)icount < pk->p_xsize) { 330: cc = icount; 331: fc = pk->p_xsize - cc; 332: *cp = fc&0177; 333: if (fc > 127) { 334: *cp++ |= 0200; 335: *cp++ = fc>>7; 336: } else 337: cp++; 338: partial = B_SHORT; 339: } else 340: cc = pk->p_xsize; 341: pkmove(cp, ibuf, cc, B_WRITE); 342: ibuf += cc; 343: icount -= cc; 344: pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); 345: pk->p_os[x] = B_READY+partial; 346: pkoutput(pk); 347: } while (icount); 348: 349: return count; 350: } 351: 352: pksack(pk) 353: register struct pack *pk; 354: { 355: register x, i; 356: 357: i = 0; 358: for(x=pk->p_ps; x!=pk->p_rpr; ) { 359: x = next[x]; 360: if (pk->p_os[x]&B_SENT) { 361: i++; 362: pk->p_os[x] = B_NULL; 363: pk->p_state &= ~WAITO; 364: pk->p_xcount--; 365: free((char *)pk->p_ob[x]); 366: pk->p_ps = x; 367: } 368: } 369: return i; 370: } 371: 372: pkoutput(pk) 373: register struct pack *pk; 374: { 375: register x; 376: int i; 377: char bstate; 378: 379: if (pk->p_obusy++) { 380: pk->p_obusy--; 381: return; 382: } 383: 384: /* 385: * find seq number and buffer state 386: * of next output packet 387: */ 388: if (pk->p_state&RXMIT) { 389: pk->p_nxtps = next[pk->p_rpr]; 390: } 391: x = pk->p_nxtps; 392: bstate = pk->p_os[x]; 393: 394: /* 395: * Send control packet if indicated 396: */ 397: if (pk->p_msg) { 398: if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { 399: x = pk->p_msg; 400: for(i=0; i<8; i++) 401: if (x&1) 402: break; 403: else 404: x >>= 1; 405: x = i; 406: x <<= 3; 407: switch(i) { 408: case CLOSE: 409: break; 410: case RJ: 411: case RR: 412: x += pk->p_pr; 413: break; 414: case SRJ: 415: break; 416: case INITB: 417: x += pksize(pk->p_rsize); 418: break; 419: case INITC: 420: x += pk->p_rwindow; 421: break; 422: case INITA: 423: x += pk->p_rwindow; 424: break; 425: } 426: 427: pk->p_msg &= ~mask[i]; 428: pkxstart(pk, x, -1); 429: goto out; 430: } 431: } 432: 433: 434: /* 435: * Don't send data packets if line is marked dead. 436: */ 437: if (pk->p_state&DOWN) { 438: goto out; 439: } 440: /* 441: * Start transmission (or retransmission) of data packets. 442: */ 443: if (bstate & (B_READY|B_SENT)) { 444: char seq; 445: 446: bstate |= B_SENT; 447: seq = x; 448: pk->p_nxtps = next[x]; 449: 450: x = 0200+pk->p_pr+(seq<<3); 451: if (bstate & B_SHORT) 452: x |= 0100; 453: pkxstart(pk, x, seq); 454: pk->p_os[seq] = bstate; 455: pk->p_state &= ~RXMIT; 456: pk->p_nout++; 457: goto out; 458: } 459: /* 460: * enable timeout if there's nothing to send 461: * and transmission buffers are languishing 462: */ 463: if (pk->p_xcount) { 464: pk->p_timer = 2; 465: pk->p_state |= WAITO; 466: } else 467: pk->p_state &= ~WAITO; 468: out: 469: pk->p_obusy = 0; 470: } 471: 472: /* 473: * shut down line by 474: * ignoring new input 475: * letting output drain 476: * releasing space and turning off line discipline 477: */ 478: /*ARGSUSED*/ 479: pkclose(pk) 480: register struct pack *pk; 481: { 482: register i; 483: char **bp; 484: int rcheck = 0; 485: 486: pk->p_state |= DRAINO; 487: 488: /* 489: * try to flush output 490: */ 491: i = 0; 492: pk->p_timer = 2; 493: while (pk->p_xcount && pk->p_state&LIVE) { 494: if (pk->p_state&(RCLOSE+DOWN) || ++i > 2) 495: break; 496: pkoutput(pk); 497: } 498: pk->p_timer = 0; 499: pk->p_state |= DOWN; 500: 501: /* 502: * try to exchange CLOSE messages 503: */ 504: i = 0; 505: while ((pk->p_state&RCLOSE)==0 && i<2) { 506: pk->p_msg = M_CLOSE; 507: pk->p_timer = 2; 508: pkoutput(pk); 509: i++; 510: } 511: 512: for(i=0;i<NPLINES;i++) 513: if (pklines[i]==pk) { 514: pklines[i] = NULL; 515: } 516: 517: /* 518: * free space 519: */ 520: rcheck = 0; 521: for (i=0;i<8;i++) { 522: if (pk->p_os[i] != B_NULL) { 523: free((char *)pk->p_ob[i]); 524: pk->p_xcount--; 525: } 526: if (pk->p_is[i] != B_NULL) { 527: free((char *)pk->p_ib[i]); 528: rcheck++; 529: } 530: } 531: while (pk->p_ipool != NULL) { 532: bp = pk->p_ipool; 533: pk->p_ipool = (char **)*bp; 534: rcheck++; 535: free((char *)bp); 536: } 537: if (rcheck != pk->p_rwindow) { 538: char buf[256]; 539: 540: sprintf(buf, "PK0: rc %d rw %d", rcheck, pk->p_rwindow); 541: logent(buf, "pkclose rcheck != p_rwindow"); 542: } 543: free((char *)pk); 544: } 545: 546: pkreset(pk) 547: register struct pack *pk; 548: { 549: 550: pk->p_ps = pk->p_pr = pk->p_rpr = 0; 551: pk->p_nxtps = 1; 552: } 553: 554: #ifndef BSD4_2 555: bzero(s,n) 556: register char *s; 557: register n; 558: { 559: while (n--) 560: *s++ = 0; 561: } 562: #endif !BSD4_2 563: 564: pksize(n) 565: register n; 566: { 567: register k; 568: 569: n >>= 5; 570: for(k=0; n >>= 1; k++) 571: ; 572: return k; 573: }