1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1995 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include "uucp.h" 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #include "pk.h" 36*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate extern void pkfail(), pkzero(), pkoutput(), pkreset(), pkcntl(), pkgetpack(); 39*7c478bd9Sstevel@tonic-gate extern int pksack(); 40*7c478bd9Sstevel@tonic-gate static void pkdata(); 41*7c478bd9Sstevel@tonic-gate static int pkcget(); 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate * Code added to allow translation of states from numbers to 45*7c478bd9Sstevel@tonic-gate * letters, to be done in such a way as to be meaningful to 46*7c478bd9Sstevel@tonic-gate * John Q. Public 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate struct { 49*7c478bd9Sstevel@tonic-gate int state; 50*7c478bd9Sstevel@tonic-gate char *msg; 51*7c478bd9Sstevel@tonic-gate } st_trans[] = { 52*7c478bd9Sstevel@tonic-gate DEAD, "Dead!", 53*7c478bd9Sstevel@tonic-gate INITa, "INIT code a", 54*7c478bd9Sstevel@tonic-gate INITb, "INIT code b", 55*7c478bd9Sstevel@tonic-gate LIVE, "O.K.", 56*7c478bd9Sstevel@tonic-gate RXMIT, "Rcv/Xmit", 57*7c478bd9Sstevel@tonic-gate RREJ, "RREJ?", 58*7c478bd9Sstevel@tonic-gate PDEBUG, "PDEBUG?", 59*7c478bd9Sstevel@tonic-gate DRAINO, "Draino...", 60*7c478bd9Sstevel@tonic-gate WAITO, "Waiting", 61*7c478bd9Sstevel@tonic-gate DOWN, "Link down", 62*7c478bd9Sstevel@tonic-gate RCLOSE, "RCLOSE?", 63*7c478bd9Sstevel@tonic-gate BADFRAME, "Bad frame", 64*7c478bd9Sstevel@tonic-gate -1, "End of the line", 65*7c478bd9Sstevel@tonic-gate }; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate extern char _Protocol[]; /* Protocol string with (options) */ 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #define PKMAXSTMSG 40 70*7c478bd9Sstevel@tonic-gate int Connodata = 0; /* Continuous Non Valid Data Count */ 71*7c478bd9Sstevel@tonic-gate int Ntimeout = 0; 72*7c478bd9Sstevel@tonic-gate #define CONNODATA 20 /* Max Continuous Non Valid Data Count */ 73*7c478bd9Sstevel@tonic-gate #define NTIMEOUT 50 /* This is not currently used, but maybe future */ 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate extern jmp_buf Getjbuf; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate /* 78*7c478bd9Sstevel@tonic-gate * start initial synchronization. 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate struct pack * 81*7c478bd9Sstevel@tonic-gate pkopen(ifn, ofn) 82*7c478bd9Sstevel@tonic-gate int ifn, ofn; 83*7c478bd9Sstevel@tonic-gate { 84*7c478bd9Sstevel@tonic-gate register struct pack *pk; 85*7c478bd9Sstevel@tonic-gate register char **bp; 86*7c478bd9Sstevel@tonic-gate register int i; 87*7c478bd9Sstevel@tonic-gate int windows = WINDOWS; 88*7c478bd9Sstevel@tonic-gate extern int xpacksize, packsize; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate if ((pk = (struct pack *) calloc(1, sizeof (struct pack))) == NULL) 91*7c478bd9Sstevel@tonic-gate return(NULL); 92*7c478bd9Sstevel@tonic-gate pk->p_ifn = ifn; 93*7c478bd9Sstevel@tonic-gate pk->p_ofn = ofn; 94*7c478bd9Sstevel@tonic-gate DEBUG(7, "Setting up protocol parameters '%s'\n", _Protocol); 95*7c478bd9Sstevel@tonic-gate if ( _Protocol[1] == '(' ) { 96*7c478bd9Sstevel@tonic-gate if (sscanf(_Protocol, "%*c(%d,%d)", &windows, &packsize) == 0) 97*7c478bd9Sstevel@tonic-gate sscanf(_Protocol, "%*c(,%d)", &packsize); 98*7c478bd9Sstevel@tonic-gate windows = ( windows < MINWINDOWS ? WINDOWS : 99*7c478bd9Sstevel@tonic-gate ( windows > MAXWINDOWS ? WINDOWS : windows ) ); 100*7c478bd9Sstevel@tonic-gate packsize = ( packsize < MINPACKSIZE ? PACKSIZE : 101*7c478bd9Sstevel@tonic-gate ( packsize > MAXPACKSIZE ? PACKSIZE : packsize ) ); 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate if ( (_Protocol[0] == 'g') && (packsize > OLDPACKSIZE) ) { 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * We reset to OLDPACKSIZE to maintain compatibility 106*7c478bd9Sstevel@tonic-gate * with old limited implementations. Maybe we should 107*7c478bd9Sstevel@tonic-gate * just warn the administrator and continue? 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate packsize = OLDPACKSIZE; 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate pk->p_xsize = pk->p_rsize = xpacksize = packsize; 112*7c478bd9Sstevel@tonic-gate pk->p_rwindow = pk->p_swindow = windows; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * allocate input window 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate for (i = 0; i < pk->p_rwindow; i++) { 118*7c478bd9Sstevel@tonic-gate if ((bp = (char **) malloc((unsigned) pk->p_xsize)) == NULL) 119*7c478bd9Sstevel@tonic-gate break; 120*7c478bd9Sstevel@tonic-gate *bp = (char *) pk->p_ipool; 121*7c478bd9Sstevel@tonic-gate pk->p_ipool = bp; 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate if (i == 0) 124*7c478bd9Sstevel@tonic-gate return(NULL); 125*7c478bd9Sstevel@tonic-gate pk->p_rwindow = i; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * start synchronization 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate pk->p_msg = pk->p_rmsg = M_INITA; 131*7c478bd9Sstevel@tonic-gate pkoutput(pk); 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate for (i = 0; i < PKMAXSTMSG; i++) { 134*7c478bd9Sstevel@tonic-gate pkgetpack(pk); 135*7c478bd9Sstevel@tonic-gate if ((pk->p_state & LIVE) != 0) 136*7c478bd9Sstevel@tonic-gate break; 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate if (i >= PKMAXSTMSG) 139*7c478bd9Sstevel@tonic-gate return(NULL); 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate pkreset(pk); 142*7c478bd9Sstevel@tonic-gate return(pk); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * input framing and block checking. 147*7c478bd9Sstevel@tonic-gate * frame layout for most devices is: 148*7c478bd9Sstevel@tonic-gate * 149*7c478bd9Sstevel@tonic-gate * S|K|X|Y|C|Z| ... data ... | 150*7c478bd9Sstevel@tonic-gate * 151*7c478bd9Sstevel@tonic-gate * where S == initial synch byte 152*7c478bd9Sstevel@tonic-gate * K == encoded frame size (indexes pksizes[]) 153*7c478bd9Sstevel@tonic-gate * X, Y == block check bytes 154*7c478bd9Sstevel@tonic-gate * C == control byte 155*7c478bd9Sstevel@tonic-gate * Z == XOR of header (K^X^Y^C) 156*7c478bd9Sstevel@tonic-gate * data == 0 or more data bytes 157*7c478bd9Sstevel@tonic-gate * 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate #define GETRIES 10 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * Byte collection. 163*7c478bd9Sstevel@tonic-gate */ 164*7c478bd9Sstevel@tonic-gate void 165*7c478bd9Sstevel@tonic-gate pkgetpack(ipk) 166*7c478bd9Sstevel@tonic-gate register struct pack *ipk; 167*7c478bd9Sstevel@tonic-gate { 168*7c478bd9Sstevel@tonic-gate register char *p; 169*7c478bd9Sstevel@tonic-gate register struct pack *pk; 170*7c478bd9Sstevel@tonic-gate register struct header *h; 171*7c478bd9Sstevel@tonic-gate unsigned short sum; 172*7c478bd9Sstevel@tonic-gate int k, tries, ifn, noise; 173*7c478bd9Sstevel@tonic-gate char **bp, hdchk; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate pk = ipk; 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * If we are known to be DOWN, or if we've received too many garbage 178*7c478bd9Sstevel@tonic-gate * packets or timeouts, give up without a fight. 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate if ((pk->p_state & DOWN) || Connodata > CONNODATA || Ntimeout > NTIMEOUT) 181*7c478bd9Sstevel@tonic-gate pkfail(); 182*7c478bd9Sstevel@tonic-gate ifn = pk->p_ifn; 183*7c478bd9Sstevel@tonic-gate h = &pk->p_ihbuf; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * Attempt no more than GETRIES times to read a packet. The only valid 187*7c478bd9Sstevel@tonic-gate * exit from this loop is a return. Break forces a failure. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate for (tries = 0; tries < GETRIES; tries++) { 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * Read header. 192*7c478bd9Sstevel@tonic-gate * First look for SYN. If more than 3 * packetsize characters 193*7c478bd9Sstevel@tonic-gate * go by w/o a SYN, request a retransmit. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate p = (caddr_t) h; 196*7c478bd9Sstevel@tonic-gate noise = 0; 197*7c478bd9Sstevel@tonic-gate for ( ; ; ) { 198*7c478bd9Sstevel@tonic-gate if (pkcget(ifn, p, HDRSIZ) != SUCCESS) { 199*7c478bd9Sstevel@tonic-gate DEBUG(7, 200*7c478bd9Sstevel@tonic-gate "Alarm while looking for SYN -- request RXMIT\n%s", ""); 201*7c478bd9Sstevel@tonic-gate goto retransmit; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate if (*p == SYN) 204*7c478bd9Sstevel@tonic-gate break; /* got it */ 205*7c478bd9Sstevel@tonic-gate else { 206*7c478bd9Sstevel@tonic-gate char *pp, *pend; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate DEBUG(7, "first char not SYN (%x)\n", *p&0xff); 209*7c478bd9Sstevel@tonic-gate if ((pp = memchr(p, SYN, HDRSIZ)) != NULL) { 210*7c478bd9Sstevel@tonic-gate pend = p + HDRSIZ; 211*7c478bd9Sstevel@tonic-gate while (pp < pend) 212*7c478bd9Sstevel@tonic-gate *p++ = *pp++; 213*7c478bd9Sstevel@tonic-gate /* Now look for remainder of header */ 214*7c478bd9Sstevel@tonic-gate if (pkcget(ifn, p, pend - p) != 215*7c478bd9Sstevel@tonic-gate SUCCESS) { 216*7c478bd9Sstevel@tonic-gate DEBUG(7, 217*7c478bd9Sstevel@tonic-gate "Alarm while looking for header -- request RXMIT\n%s", ""); 218*7c478bd9Sstevel@tonic-gate goto retransmit; 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate p = (caddr_t) h; 221*7c478bd9Sstevel@tonic-gate break; /* got entire header */ 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate if ((noise += HDRSIZ) > 3 * pk->p_rsize) { 225*7c478bd9Sstevel@tonic-gate DEBUG(7, 226*7c478bd9Sstevel@tonic-gate "No SYN in %d characters -- request RXMIT\n", noise); 227*7c478bd9Sstevel@tonic-gate goto retransmit; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate /* Validate the header */ 231*7c478bd9Sstevel@tonic-gate Connodata++; 232*7c478bd9Sstevel@tonic-gate hdchk = p[1] ^ p[2] ^ p[3] ^ p[4]; 233*7c478bd9Sstevel@tonic-gate sum = ((unsigned) p[2] & 0377) | ((unsigned) p[3] << 8); 234*7c478bd9Sstevel@tonic-gate h->sum = sum; 235*7c478bd9Sstevel@tonic-gate k = h->ksize; 236*7c478bd9Sstevel@tonic-gate if (hdchk != h->ccntl) { 237*7c478bd9Sstevel@tonic-gate /* bad header */ 238*7c478bd9Sstevel@tonic-gate DEBUG(7, "bad header checksum\n%s", ""); 239*7c478bd9Sstevel@tonic-gate return; 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate if (k == 9) { /* control packet */ 243*7c478bd9Sstevel@tonic-gate if (((h->sum + h->cntl) & 0xffff) == CHECK) { 244*7c478bd9Sstevel@tonic-gate pkcntl(h->cntl, pk); 245*7c478bd9Sstevel@tonic-gate xlatestate(pk, 7); 246*7c478bd9Sstevel@tonic-gate } else { 247*7c478bd9Sstevel@tonic-gate /* bad header */ 248*7c478bd9Sstevel@tonic-gate DEBUG(7, "bad header (k == 9) 0%o\n", h->cntl&0xff); 249*7c478bd9Sstevel@tonic-gate pk->p_state |= BADFRAME; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate return; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate /* data packet */ 254*7c478bd9Sstevel@tonic-gate if (k && pksizes[k] != pk->p_rsize) 255*7c478bd9Sstevel@tonic-gate return; 256*7c478bd9Sstevel@tonic-gate pk->p_rpr = h->cntl & MOD8; 257*7c478bd9Sstevel@tonic-gate pksack(pk); 258*7c478bd9Sstevel@tonic-gate if ((bp = pk->p_ipool) == NULL) { 259*7c478bd9Sstevel@tonic-gate DEBUG(7, "bp NULL\n%s", ""); 260*7c478bd9Sstevel@tonic-gate return; 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate pk->p_ipool = (char **) *bp; 263*7c478bd9Sstevel@tonic-gate /* Header checks out, go for data */ 264*7c478bd9Sstevel@tonic-gate if (pkcget(pk->p_ifn, (char *) bp, pk->p_rsize) == SUCCESS) { 265*7c478bd9Sstevel@tonic-gate pkdata(h->cntl, h->sum, pk, bp); 266*7c478bd9Sstevel@tonic-gate Ntimeout = 0; 267*7c478bd9Sstevel@tonic-gate return; 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate DEBUG(7, "Alarm while reading data -- request RXMIT\n%s", ""); 270*7c478bd9Sstevel@tonic-gate retransmit: 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * Transmission error or excessive noise. Send a RXMIT 273*7c478bd9Sstevel@tonic-gate * and try again. 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate Retries++; 277*7c478bd9Sstevel@tonic-gate */ 278*7c478bd9Sstevel@tonic-gate pk->p_msg |= pk->p_rmsg; 279*7c478bd9Sstevel@tonic-gate if (pk->p_msg == 0) 280*7c478bd9Sstevel@tonic-gate pk->p_msg |= M_RR; 281*7c478bd9Sstevel@tonic-gate if ((pk->p_state & LIVE) == LIVE) 282*7c478bd9Sstevel@tonic-gate pk->p_state |= RXMIT; 283*7c478bd9Sstevel@tonic-gate pkoutput(pk); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate DEBUG(7, "pkgetpack failed after %d tries\n", tries); 286*7c478bd9Sstevel@tonic-gate pkfail(); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * Translate pk->p_state into something printable. 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate xlatestate(pk, dbglvl) 293*7c478bd9Sstevel@tonic-gate register struct pack *pk; 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate register int i; 296*7c478bd9Sstevel@tonic-gate char delimc = ' ', msgline[80], *buf = msgline; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate if (Debug < dbglvl) 299*7c478bd9Sstevel@tonic-gate return; 300*7c478bd9Sstevel@tonic-gate sprintf(buf, "state -"); 301*7c478bd9Sstevel@tonic-gate buf += strlen(buf); 302*7c478bd9Sstevel@tonic-gate for(i = 0; st_trans[i].state != -1; i++) { 303*7c478bd9Sstevel@tonic-gate if (pk->p_state&st_trans[i].state){ 304*7c478bd9Sstevel@tonic-gate sprintf(buf, "%c[%s]", delimc, st_trans[i].msg); 305*7c478bd9Sstevel@tonic-gate buf += strlen(buf); 306*7c478bd9Sstevel@tonic-gate delimc = '&'; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate sprintf(buf, " (0%o)\n", pk->p_state); 310*7c478bd9Sstevel@tonic-gate DEBUG(dbglvl, "%s", msgline); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate static void 314*7c478bd9Sstevel@tonic-gate pkdata(c, sum, pk, bp) 315*7c478bd9Sstevel@tonic-gate register struct pack *pk; 316*7c478bd9Sstevel@tonic-gate unsigned short sum; 317*7c478bd9Sstevel@tonic-gate char c; 318*7c478bd9Sstevel@tonic-gate char **bp; 319*7c478bd9Sstevel@tonic-gate { 320*7c478bd9Sstevel@tonic-gate register x; 321*7c478bd9Sstevel@tonic-gate int t; 322*7c478bd9Sstevel@tonic-gate char m; 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) { 325*7c478bd9Sstevel@tonic-gate pk->p_msg |= pk->p_rmsg; 326*7c478bd9Sstevel@tonic-gate pkoutput(pk); 327*7c478bd9Sstevel@tonic-gate goto drop; 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate t = next[pk->p_pr]; 330*7c478bd9Sstevel@tonic-gate for(x=pk->p_pr; x!=t; x = (x-1)&7) { 331*7c478bd9Sstevel@tonic-gate if (pk->p_is[x] == 0) 332*7c478bd9Sstevel@tonic-gate goto slot; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate drop: 335*7c478bd9Sstevel@tonic-gate *bp = (char *)pk->p_ipool; 336*7c478bd9Sstevel@tonic-gate pk->p_ipool = bp; 337*7c478bd9Sstevel@tonic-gate return; 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate slot: 340*7c478bd9Sstevel@tonic-gate m = mask[x]; 341*7c478bd9Sstevel@tonic-gate pk->p_imap |= m; 342*7c478bd9Sstevel@tonic-gate pk->p_is[x] = c; 343*7c478bd9Sstevel@tonic-gate pk->p_isum[x] = sum; 344*7c478bd9Sstevel@tonic-gate pk->p_ib[x] = (char *)bp; 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * Start transmission on output device associated with pk. 349*7c478bd9Sstevel@tonic-gate * For asynch devices (t_line==1) framing is 350*7c478bd9Sstevel@tonic-gate * imposed. For devices with framing and crc 351*7c478bd9Sstevel@tonic-gate * in the driver (t_line==2) the transfer is 352*7c478bd9Sstevel@tonic-gate * passed on to the driver. 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate void 355*7c478bd9Sstevel@tonic-gate pkxstart(pk, cntl, x) 356*7c478bd9Sstevel@tonic-gate register struct pack *pk; 357*7c478bd9Sstevel@tonic-gate int x; 358*7c478bd9Sstevel@tonic-gate char cntl; 359*7c478bd9Sstevel@tonic-gate { 360*7c478bd9Sstevel@tonic-gate register char *p; 361*7c478bd9Sstevel@tonic-gate register short checkword; 362*7c478bd9Sstevel@tonic-gate register char hdchk; 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate p = (caddr_t) &pk->p_ohbuf; 365*7c478bd9Sstevel@tonic-gate *p++ = SYN; 366*7c478bd9Sstevel@tonic-gate if (x < 0) { 367*7c478bd9Sstevel@tonic-gate *p++ = hdchk = 9; 368*7c478bd9Sstevel@tonic-gate checkword = cntl; 369*7c478bd9Sstevel@tonic-gate } else { 370*7c478bd9Sstevel@tonic-gate *p++ = hdchk = pk->p_lpsize; 371*7c478bd9Sstevel@tonic-gate checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate checkword = CHECK - checkword; 374*7c478bd9Sstevel@tonic-gate *p = checkword; 375*7c478bd9Sstevel@tonic-gate hdchk ^= *p++; 376*7c478bd9Sstevel@tonic-gate *p = checkword>>8; 377*7c478bd9Sstevel@tonic-gate hdchk ^= *p++; 378*7c478bd9Sstevel@tonic-gate *p = cntl; 379*7c478bd9Sstevel@tonic-gate hdchk ^= *p++; 380*7c478bd9Sstevel@tonic-gate *p = hdchk; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * writes 384*7c478bd9Sstevel@tonic-gate */ 385*7c478bd9Sstevel@tonic-gate if (Debug >= 9) 386*7c478bd9Sstevel@tonic-gate xlatecntl(1, cntl); 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate p = (caddr_t) & pk->p_ohbuf; 389*7c478bd9Sstevel@tonic-gate if (x < 0) { 390*7c478bd9Sstevel@tonic-gate if ((*Write)(pk->p_ofn, p, HDRSIZ) != HDRSIZ) { 391*7c478bd9Sstevel@tonic-gate DEBUG(4, "pkxstart, write failed, %s\n", 392*7c478bd9Sstevel@tonic-gate sys_errlist[errno]); 393*7c478bd9Sstevel@tonic-gate logent(sys_errlist[errno], "PKXSTART WRITE"); 394*7c478bd9Sstevel@tonic-gate pkfail(); 395*7c478bd9Sstevel@tonic-gate /* NOT REACHED */ 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate } else { 398*7c478bd9Sstevel@tonic-gate char buf[MAXPACKSIZE + HDRSIZ]; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate memcpy(buf, p, HDRSIZ); 401*7c478bd9Sstevel@tonic-gate memcpy(buf+HDRSIZ, pk->p_ob[x], pk->p_xsize); 402*7c478bd9Sstevel@tonic-gate if ((*Write)(pk->p_ofn, buf, pk->p_xsize + HDRSIZ) != 403*7c478bd9Sstevel@tonic-gate pk->p_xsize + HDRSIZ) { 404*7c478bd9Sstevel@tonic-gate DEBUG(4, "pkxstart, write failed, %s\n", 405*7c478bd9Sstevel@tonic-gate sys_errlist[errno]); 406*7c478bd9Sstevel@tonic-gate logent(sys_errlist[errno], "PKXSTART WRITE"); 407*7c478bd9Sstevel@tonic-gate pkfail(); 408*7c478bd9Sstevel@tonic-gate /* NOT REACHED */ 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate Connodata = 0; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate if (pk->p_msg) 413*7c478bd9Sstevel@tonic-gate pkoutput(pk); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* 417*7c478bd9Sstevel@tonic-gate * get n characters from input 418*7c478bd9Sstevel@tonic-gate * b -> buffer for characters 419*7c478bd9Sstevel@tonic-gate * fn -> file descriptor 420*7c478bd9Sstevel@tonic-gate * n -> requested number of characters 421*7c478bd9Sstevel@tonic-gate * return: 422*7c478bd9Sstevel@tonic-gate * SUCCESS -> n chars successfully read 423*7c478bd9Sstevel@tonic-gate * FAIL -> o.w. 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate static int 427*7c478bd9Sstevel@tonic-gate pkcget(fn, b, n) 428*7c478bd9Sstevel@tonic-gate register int n; 429*7c478bd9Sstevel@tonic-gate register char *b; 430*7c478bd9Sstevel@tonic-gate register int fn; 431*7c478bd9Sstevel@tonic-gate { 432*7c478bd9Sstevel@tonic-gate register int ret; 433*7c478bd9Sstevel@tonic-gate #ifdef PKSPEEDUP 434*7c478bd9Sstevel@tonic-gate extern int linebaudrate; 435*7c478bd9Sstevel@tonic-gate register int donap = (linebaudrate > 0 && linebaudrate < 4800); 436*7c478bd9Sstevel@tonic-gate #endif /* PKSPEEDUP */ 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate if (n == 0) 439*7c478bd9Sstevel@tonic-gate return(SUCCESS); 440*7c478bd9Sstevel@tonic-gate if (setjmp(Getjbuf)) { 441*7c478bd9Sstevel@tonic-gate Ntimeout++; 442*7c478bd9Sstevel@tonic-gate DEBUG(4, "pkcget: alarm %d\n", Ntimeout); 443*7c478bd9Sstevel@tonic-gate return(FAIL); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate (void) alarm( (unsigned) ( 10 + (n >> 7)) ); 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate for (;;) { 449*7c478bd9Sstevel@tonic-gate ret = (*Read)(fn, b, n); 450*7c478bd9Sstevel@tonic-gate (void) alarm(0); 451*7c478bd9Sstevel@tonic-gate if (ret == 0) { 452*7c478bd9Sstevel@tonic-gate DEBUG(4, "pkcget, read failed, EOF\n", 0); 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * Device has decided that the connection has no 455*7c478bd9Sstevel@tonic-gate * more data to send. Any further tries are futile... 456*7c478bd9Sstevel@tonic-gate * (The only other way to get a zero return value 457*7c478bd9Sstevel@tonic-gate * is to read a zero length message from a STREAM. 458*7c478bd9Sstevel@tonic-gate * However, uucp *never* sends zero length messages 459*7c478bd9Sstevel@tonic-gate * over any sort of channel...) 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate pkfail(); 462*7c478bd9Sstevel@tonic-gate /* NOT REACHED */ 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate if (ret < 0) { 465*7c478bd9Sstevel@tonic-gate DEBUG(4, "pkcget, read failed, %s\n", 466*7c478bd9Sstevel@tonic-gate sys_errlist[errno]); 467*7c478bd9Sstevel@tonic-gate logent(sys_errlist[errno], "PKCGET READ"); 468*7c478bd9Sstevel@tonic-gate pkfail(); 469*7c478bd9Sstevel@tonic-gate /* NOT REACHED */ 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate if ((n -= ret) <= 0) 472*7c478bd9Sstevel@tonic-gate break; 473*7c478bd9Sstevel@tonic-gate #ifdef PKSPEEDUP 474*7c478bd9Sstevel@tonic-gate if (donap) { 475*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4) 476*7c478bd9Sstevel@tonic-gate /* wait for more chars to come in */ 477*7c478bd9Sstevel@tonic-gate nap((n * HZ * 10) / linebaudrate); /* n char times */ 478*7c478bd9Sstevel@tonic-gate #else 479*7c478bd9Sstevel@tonic-gate sleep(1); 480*7c478bd9Sstevel@tonic-gate #endif 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate #endif /* PKSPEEDUP */ 483*7c478bd9Sstevel@tonic-gate b += ret; 484*7c478bd9Sstevel@tonic-gate (void) alarm( (unsigned) ( 10 + (n >> 7)) ); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate (void) alarm(0); 487*7c478bd9Sstevel@tonic-gate return(SUCCESS); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate /* 491*7c478bd9Sstevel@tonic-gate * role == 0: receive 492*7c478bd9Sstevel@tonic-gate * role == 1: send 493*7c478bd9Sstevel@tonic-gate */ 494*7c478bd9Sstevel@tonic-gate xlatecntl(role, cntl) 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate static char *cntltype[4] = {"CNTL, ", "ALT, ", "DATA, ", "SHORT, "}; 497*7c478bd9Sstevel@tonic-gate static char *cntlxxx[8] = {"ZERO, ", "CLOSE, ", "RJ, ", "SRJ, ", 498*7c478bd9Sstevel@tonic-gate "RR, ", "INITC, ", "INITB, ", "INITA, "}; 499*7c478bd9Sstevel@tonic-gate char dbgbuf[128]; 500*7c478bd9Sstevel@tonic-gate register char *ptr; 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate ptr = dbgbuf; 503*7c478bd9Sstevel@tonic-gate strcpy(ptr, role ? "send " : "recv "); 504*7c478bd9Sstevel@tonic-gate ptr += strlen(ptr); 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate strcpy(ptr, cntltype[(cntl&0300)>>6]); 507*7c478bd9Sstevel@tonic-gate ptr += strlen(ptr); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate if (cntl&0300) { 510*7c478bd9Sstevel@tonic-gate /* data packet */ 511*7c478bd9Sstevel@tonic-gate if (role) 512*7c478bd9Sstevel@tonic-gate sprintf(ptr, "loc %o, rem %o\n", (cntl & 070) >> 3, cntl & 7); 513*7c478bd9Sstevel@tonic-gate else 514*7c478bd9Sstevel@tonic-gate sprintf(ptr, "loc %o, rem %o\n", cntl & 7, (cntl & 070) >> 3); 515*7c478bd9Sstevel@tonic-gate } else { 516*7c478bd9Sstevel@tonic-gate /* control packet */ 517*7c478bd9Sstevel@tonic-gate strcpy(ptr, cntlxxx[(cntl&070)>>3]); 518*7c478bd9Sstevel@tonic-gate ptr += strlen(ptr); 519*7c478bd9Sstevel@tonic-gate sprintf(ptr, "val %o\n", cntl & 7); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate DEBUG(1, dbgbuf, 0); 523*7c478bd9Sstevel@tonic-gate } 524