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