1 #ifndef lint 2 static char sccsid[] = "@(#)pk0.c 5.9 (Berkeley) 04/05/88"; 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 bcopy(cp, ibuf, cc); 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] = 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 bcopy(ibuf, cp, cc); 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 goto out; 457 } 458 /* 459 * enable timeout if there's nothing to send 460 * and transmission buffers are languishing 461 */ 462 if (pk->p_xcount) { 463 pk->p_state |= WAITO; 464 } else 465 pk->p_state &= ~WAITO; 466 out: 467 pk->p_obusy = 0; 468 } 469 470 /* 471 * shut down line by 472 * ignoring new input 473 * letting output drain 474 * releasing space and turning off line discipline 475 */ 476 /*ARGSUSED*/ 477 pkclose(pk) 478 register struct pack *pk; 479 { 480 register i; 481 char **bp; 482 int rcheck = 0; 483 484 pk->p_state |= DRAINO; 485 486 /* 487 * try to flush output 488 */ 489 i = 0; 490 while (pk->p_xcount && pk->p_state&LIVE) { 491 if (pk->p_state&(RCLOSE+DOWN) || ++i > 2) 492 break; 493 pkoutput(pk); 494 } 495 pk->p_state |= DOWN; 496 497 /* 498 * try to exchange CLOSE messages 499 */ 500 i = 0; 501 while ((pk->p_state&RCLOSE)==0 && i<2) { 502 pk->p_msg = M_CLOSE; 503 pkoutput(pk); 504 i++; 505 } 506 507 for(i=0;i<NPLINES;i++) 508 if (pklines[i]==pk) { 509 pklines[i] = NULL; 510 } 511 512 /* 513 * free space 514 */ 515 rcheck = 0; 516 for (i=0;i<8;i++) { 517 if (pk->p_os[i] != B_NULL) { 518 free((char *)pk->p_ob[i]); 519 pk->p_xcount--; 520 } 521 if (pk->p_is[i] != B_NULL) { 522 free((char *)pk->p_ib[i]); 523 rcheck++; 524 } 525 } 526 while (pk->p_ipool != NULL) { 527 bp = pk->p_ipool; 528 pk->p_ipool = (char **)*bp; 529 rcheck++; 530 free((char *)bp); 531 } 532 if (rcheck != pk->p_rwindow) { 533 syslog(LOG_WARNING, "%s: pk0: rc %d rw %d", Rmtname, rcheck, 534 pk->p_rwindow); 535 } 536 free((char *)pk); 537 } 538 539 pkreset(pk) 540 register struct pack *pk; 541 { 542 543 pk->p_ps = pk->p_pr = pk->p_rpr = 0; 544 pk->p_nxtps = 1; 545 } 546 547 #ifndef BSD4_2 548 bzero(s,n) 549 register char *s; 550 register n; 551 { 552 while (n--) 553 *s++ = 0; 554 } 555 #endif !BSD4_2 556 557 pksize(n) 558 register n; 559 { 560 register k; 561 562 n >>= 5; 563 for(k=0; n >>= 1; k++) 564 ; 565 return k; 566 } 567