1: static char sccsid[]="@(#)pk1.c 4.1 6/27/83 uucp-4.2BSD"; 2: extern char *malloc(); 3: 4: #define USER 1 5: #include <stdio.h> 6: #ifdef SYSIII 7: #include <sys/types.h> 8: #endif 9: #include "pk.p" 10: #include <sys/param.h> 11: #include "pk.h" 12: #include <sys/buf.h> 13: #include <setjmp.h> 14: #include <signal.h> 15: 16: 17: #define PKMAXSTMSG 40 18: #define PKTIME 25 19: extern int Errorrate; 20: int Connodata = 0; 21: int Ntimeout = 0; 22: #define CONNODATA 10 23: #define NTIMEOUT 50 24: /* 25: * packet driver support routines 26: * 27: */ 28: 29: struct pack *pklines[NPLINES]; 30: 31: /* 32: * start initial synchronization. 33: */ 34: 35: struct pack * 36: pkopen(ifn, ofn) 37: int ifn, ofn; 38: { 39: register struct pack *pk; 40: register char **bp; 41: register int i; 42: 43: if (++pkactive >= NPLINES) 44: return(NULL); 45: if ((pk = (struct pack *) malloc(sizeof (struct pack))) == NULL) 46: return(NULL); 47: pkzero((caddr_t) pk, sizeof (struct pack)); 48: pk->p_ifn = ifn; 49: pk->p_ofn = ofn; 50: pk->p_xsize = pk->p_rsize = PACKSIZE; 51: pk->p_rwindow = pk->p_swindow = WINDOWS; 52: /* allocate input windows */ 53: for (i = 0; i < pk->p_rwindow; i++) { 54: if ((bp = (char **) GETEPACK) == NULL) 55: break; 56: *bp = (char *) pk->p_ipool; 57: pk->p_ipool = bp; 58: } 59: if (i == 0) 60: return(NULL); 61: pk->p_rwindow = i; 62: 63: /* start synchronization */ 64: pk->p_msg = pk->p_rmsg = M_INITA; 65: for (i = 0; i < NPLINES; i++) { 66: if (pklines[i] == NULL) { 67: pklines[i] = pk; 68: break; 69: } 70: } 71: if (i >= NPLINES) 72: return(NULL); 73: pkoutput(pk); 74: 75: for (i = 0; i < PKMAXSTMSG; i++) { 76: PKGETPKT(pk); 77: if ((pk->p_state & LIVE) != 0) 78: break; 79: } 80: if (i >= PKMAXSTMSG) 81: return(NULL); 82: 83: pkreset(pk); 84: return(pk); 85: } 86: 87: 88: /* 89: * input framing and block checking. 90: * frame layout for most devices is: 91: * 92: * S|K|X|Y|C|Z| ... data ... | 93: * 94: * where S == initial synch byte 95: * K == encoded frame size (indexes pksizes[]) 96: * X, Y == block check bytes 97: * C == control byte 98: * Z == XOR of header (K^X^Y^C) 99: * data == 0 or more data bytes 100: * 101: */ 102: 103: int pksizes[] = { 104: 1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1 105: }; 106: 107: #define GETRIES 5 108: /* 109: * Pseudo-dma byte collection. 110: */ 111: 112: pkgetpack(ipk) 113: struct pack *ipk; 114: { 115: int ret, k, tries; 116: register char *p; 117: register struct pack *pk; 118: register struct header *h; 119: unsigned short sum; 120: int ifn; 121: char **bp; 122: char hdchk; 123: 124: pk = PADDR; 125: if ((pk->p_state & DOWN) || 126: Connodata > CONNODATA /* || Ntimeout > NTIMEOUT */) 127: pkfail(); 128: ifn = pk->p_ifn; 129: 130: /* find HEADER */ 131: for (tries = 0; tries < GETRIES; ) { 132: p = (caddr_t) &pk->p_ihbuf; 133: if ((ret = pkcget(ifn, p, 1)) < 0) { 134: /* set up retransmit or REJ */ 135: tries++; 136: pk->p_msg |= pk->p_rmsg; 137: if (pk->p_msg == 0) 138: pk->p_msg |= M_RR; 139: if ((pk->p_state & LIVE) == LIVE) 140: pk->p_state |= RXMIT; 141: pkoutput(pk); 142: continue; 143: } 144: if (*p != SYN) 145: continue; 146: p++; 147: ret = pkcget(ifn, p, HDRSIZ - 1); 148: if (ret == -1) 149: continue; 150: break; 151: } 152: if (tries >= GETRIES) { 153: PKDEBUG(4, "tries = %d\n", tries); 154: pkfail(); 155: } 156: 157: Connodata++; 158: h = (struct header * ) &pk->p_ihbuf; 159: p = (caddr_t) h; 160: hdchk = p[1] ^ p[2] ^ p[3] ^ p[4]; 161: p += 2; 162: sum = (unsigned) *p++ & 0377; 163: sum |= (unsigned) *p << 8; 164: h->sum = sum; 165: PKDEBUG(7, "rec h->cntl %o\n", (unsigned) h->cntl); 166: k = h->ksize; 167: if (hdchk != h->ccntl) { 168: /* bad header */ 169: PKDEBUG(7, "bad header %o,", hdchk); 170: PKDEBUG(7, "h->ccntl %o\n", h->ccntl); 171: return; 172: } 173: if (k == 9) { 174: if (((h->sum + h->cntl) & 0xffff) == CHECK) { 175: pkcntl(h->cntl, pk); 176: PKDEBUG(7, "state - %o\n", pk->p_state); 177: } 178: else { 179: /* bad header */ 180: PKDEBUG(7, "bad header (k==9) %o\n", h->cntl); 181: pk->p_state |= BADFRAME; 182: } 183: return; 184: } 185: if (k && pksizes[k] == pk->p_rsize) { 186: pk->p_rpr = h->cntl & MOD8; 187: pksack(pk); 188: Connodata = 0; 189: bp = pk->p_ipool; 190: pk->p_ipool = (char **) *bp; 191: if (bp == NULL) { 192: PKDEBUG(7, "bp NULL %s\n", ""); 193: return; 194: } 195: } 196: else { 197: return; 198: } 199: ret = pkcget(pk->p_ifn, (char *) bp, pk->p_rsize); 200: if (ret == 0) 201: pkdata(h->cntl, h->sum, pk, (char **) bp); 202: return; 203: } 204: 205: 206: pkdata(c, sum, pk, bp) 207: char c; 208: unsigned short sum; 209: register struct pack *pk; 210: char **bp; 211: { 212: register x; 213: int t; 214: char m; 215: 216: if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) { 217: pk->p_msg |= pk->p_rmsg; 218: pkoutput(pk); 219: goto drop; 220: } 221: t = next[pk->p_pr]; 222: for(x=pk->p_pr; x!=t; x = (x-1)&7) { 223: if (pk->p_is[x] == 0) 224: goto slot; 225: } 226: drop: 227: *bp = (char *)pk->p_ipool; 228: pk->p_ipool = bp; 229: return; 230: 231: slot: 232: m = mask[x]; 233: pk->p_imap |= m; 234: pk->p_is[x] = c; 235: pk->p_isum[x] = sum; 236: pk->p_ib[x] = (char *)bp; 237: return; 238: } 239: 240: 241: 242: /* 243: * setup input transfers 244: */ 245: pkrstart(pk) 246: {} 247: 248: #define PKMAXBUF 128 249: /* 250: * Start transmission on output device associated with pk. 251: * For asynch devices (t_line==1) framing is 252: * imposed. For devices with framing and crc 253: * in the driver (t_line==2) the transfer is 254: * passed on to the driver. 255: */ 256: pkxstart(pk, cntl, x) 257: register struct pack *pk; 258: char cntl; 259: register x; 260: { 261: register char *p; 262: int ret; 263: short checkword; 264: char hdchk; 265: 266: p = (caddr_t) &pk->p_ohbuf; 267: *p++ = SYN; 268: if (x < 0) { 269: *p++ = hdchk = 9; 270: checkword = cntl; 271: } 272: else { 273: *p++ = hdchk = pk->p_lpsize; 274: checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377); 275: } 276: checkword = CHECK - checkword; 277: *p = checkword; 278: hdchk ^= *p++; 279: *p = checkword>>8; 280: hdchk ^= *p++; 281: *p = cntl; 282: hdchk ^= *p++; 283: *p = hdchk; 284: /* writes */ 285: PKDEBUG(7, "send %o\n", (unsigned) cntl); 286: p = (caddr_t) & pk->p_ohbuf; 287: if (x < 0) { 288: #ifdef PROTODEBUG 289: GENERROR(p, HDRSIZ); 290: #endif 291: ret = write(pk->p_ofn, p, HDRSIZ); 292: PKASSERT(ret == HDRSIZ, "PKXSTART ret", "", ret); 293: } 294: else { 295: char buf[PKMAXBUF + HDRSIZ], *b; 296: int i; 297: for (i = 0, b = buf; i < HDRSIZ; i++) 298: *b++ = *p++; 299: for (i = 0, p = pk->p_ob[x]; i < pk->p_xsize; i++) 300: *b++ = *p++; 301: #ifdef PROTODEBUG 302: GENERROR(buf, pk->p_xsize + HDRSIZ); 303: #endif 304: ret = write(pk->p_ofn, buf, pk->p_xsize + HDRSIZ); 305: PKASSERT(ret == pk->p_xsize + HDRSIZ, 306: "PKXSTART ret", "", ret); 307: Connodata = 0; 308: } 309: if (pk->p_msg) 310: pkoutput(pk); 311: return; 312: } 313: 314: 315: pkmove(p1, p2, count, flag) 316: char *p1, *p2; 317: int count, flag; 318: { 319: register char *s, *d; 320: register int i; 321: 322: if (flag == B_WRITE) { 323: s = p2; 324: d = p1; 325: } 326: else { 327: s = p1; 328: d = p2; 329: } 330: for (i = 0; i < count; i++) 331: *d++ = *s++; 332: return; 333: } 334: 335: 336: /*** 337: * pkcget(fn, b, n) get n characters from input 338: * char *b; - buffer for characters 339: * int fn; - file descriptor 340: * int n; - requested number of characters 341: * 342: * return codes: 343: * n - number of characters returned 344: * 0 - end of file 345: */ 346: 347: jmp_buf Getjbuf; 348: cgalarm() { longjmp(Getjbuf, 1); } 349: 350: pkcget(fn, b, n) 351: int fn, n; 352: register char *b; 353: { 354: register int nchars, ret; 355: 356: if (setjmp(Getjbuf)) { 357: Ntimeout++; 358: PKDEBUG(4, "alarm %d\n", Ntimeout); 359: return(-1); 360: } 361: signal(SIGALRM, cgalarm); 362: 363: alarm(PKTIME); 364: for (nchars = 0; nchars < n; nchars += ret) { 365: ret = read(fn, b, n - nchars); 366: if (ret == 0) { 367: alarm(0); 368: return(-1); 369: } 370: PKASSERT(ret > 0, "PKCGET READ", "", ret); 371: b += ret; 372: } 373: alarm(0); 374: return(0); 375: } 376: 377: 378: #ifdef PROTODEBUG 379: generror(p, s) 380: char *p; 381: int s; 382: { 383: int r; 384: if (Errorrate != 0 && (rand() % Errorrate) == 0) { 385: r = rand() % s; 386: fprintf(stderr, "gen err at %o, (%o), ", r, (unsigned) *(p + r)); 387: *(p + r) += 1; 388: } 389: return; 390: } 391: 392: 393: #endif