145223Ssklower /* 245223Ssklower * X.29 server 345223Ssklower * 445223Ssklower * Frank Pronk (...!ubc-vision!pronk) 545223Ssklower * April, September 1984 645223Ssklower * 745223Ssklower * Laboratory for Computational Vision 845223Ssklower * University of British Columbia 945223Ssklower * Copyright (c) 1045223Ssklower */ 1145223Ssklower 1245223Ssklower #include <sys/param.h> 1345223Ssklower #include <sys/socket.h> 1445223Ssklower #include <sys/stat.h> 1545223Ssklower #include <sys/wait.h> 1645223Ssklower 1745223Ssklower #include <netccitt/x25.h> 1845223Ssklower 1945223Ssklower #include <errno.h> 2045223Ssklower #include <netdb.h> 2145223Ssklower #include <signal.h> 22*45293Ssklower #include <sys/ioctl.h> 23*45293Ssklower #include <sys/termios.h> 24*45293Ssklower #include <paths.h> 2545223Ssklower 2645223Ssklower #include "../h/x29.h" 2745223Ssklower 2845223Ssklower #define BUFSIZ 1024 2945223Ssklower #define MAXARGS 10 /* maximum size of server argument list */ 3045223Ssklower 3145223Ssklower #define X25NET 0 /* no ITI parameters */ 3245223Ssklower #define CCITT1978 1 /* 1978 CCITT standard parameter set */ 3345223Ssklower #define CCITT1980 2 /* 1980 CCITT standard parameter set */ 3445223Ssklower 3545223Ssklower 3645223Ssklower char pibuf[BUFSIZ], fibuf[BUFSIZ]; 3745223Ssklower int pty, net; 3845223Ssklower extern char **environ; 3945223Ssklower extern int errno; 40*45293Ssklower char line[MAXPATHLEN]; 4145223Ssklower char console[] = "/dev/console"; 4245223Ssklower short packet_size; 43*45293Ssklower short debug; 4445223Ssklower char *tracefn; /* trace file name */ 4545223Ssklower char *server; 4645223Ssklower short send_banner; 4745223Ssklower struct sockaddr_x25 sock; 4845223Ssklower 4945223Ssklower int reapchild(); 5045223Ssklower struct net *lookup (); 5145223Ssklower 5245223Ssklower char ccitt1978_prof[] = { /* initial profile */ 5345223Ssklower Q_BIT, X29_SET_AND_READ_PARMS, 5445223Ssklower X29_ECHO_CODE, 1, /* echo on */ 5545223Ssklower X29_FORWARDING_SIGNAL_CODE, 126, /* forward on all cntl */ 5645223Ssklower X29_IDLE_TIMER_CODE, 0, /* off */ 5745223Ssklower X29_AUX_DEV_CONTROL_CODE, 0, /* off */ 5845223Ssklower X29_RECEIVE_NET_MSGS_CODE, 1, /* xmit network msgs */ 5945223Ssklower X29_BREAK_PROCEDURE_CODE, 21, 6045223Ssklower X29_PADDING_CODE, 0, /* off */ 6145223Ssklower X29_LINE_FOLDING_CODE, 0, /* off */ 6245223Ssklower X29_TRANSMISSION_SPEED_CODE, 0, 6345223Ssklower X29_XON_XOFF_CODE, 1, /* enable XON/XOFF */ 6445223Ssklower }; 6545223Ssklower 6645223Ssklower char ccitt1980_prof[] = { /* initial profile */ 6745223Ssklower Q_BIT, X29_SET_AND_READ_PARMS, 6845223Ssklower X29_ECHO_CODE, 1, /* echo on */ 6945223Ssklower X29_FORWARDING_SIGNAL_CODE, 126, /* forward on all cntl */ 7045223Ssklower X29_IDLE_TIMER_CODE, 0, /* off */ 7145223Ssklower X29_AUX_DEV_CONTROL_CODE, 0, /* off */ 7245223Ssklower X29_RECEIVE_NET_MSGS_CODE, 1, /* xmit network msgs */ 7345223Ssklower X29_BREAK_PROCEDURE_CODE, 21, 7445223Ssklower X29_PADDING_CODE, 0, /* off */ 7545223Ssklower X29_LINE_FOLDING_CODE, 0, /* off */ 7645223Ssklower X29_TRANSMISSION_SPEED_CODE, 0, 7745223Ssklower X29_XON_XOFF_CODE, 1, /* enable XON/XOFF */ 7845223Ssklower 7945223Ssklower X29_LF_AFTER_CR, 4, /* lf after cr from terminal */ 8045223Ssklower X29_EDITING, 1, /* on */ 8145223Ssklower X29_CHARACTER_DELETE, CERASE, 8245223Ssklower X29_LINE_DELETE, CKILL, 8345223Ssklower X29_LINE_DISPLAY, CRPRNT, 8445223Ssklower }; 8545223Ssklower 8645223Ssklower char datapac_prof[] = { /* Canadian X.25 network */ 8745223Ssklower Q_BIT, X29_SET_AND_READ_PARMS, 8845223Ssklower X29_ECHO_CODE, 1, /* echo on */ 8945223Ssklower X29_FORWARDING_SIGNAL_CODE, 126, /* forward on all cntl */ 9045223Ssklower X29_IDLE_TIMER_CODE, 0, /* off */ 9145223Ssklower X29_AUX_DEV_CONTROL_CODE, 0, /* off */ 9245223Ssklower X29_RECEIVE_NET_MSGS_CODE, 1, /* xmit network msgs */ 9345223Ssklower X29_BREAK_PROCEDURE_CODE, 21, 9445223Ssklower X29_PADDING_CODE, 0, /* off */ 9545223Ssklower X29_LINE_FOLDING_CODE, 0, /* off */ 9645223Ssklower X29_TRANSMISSION_SPEED_CODE, 0, 9745223Ssklower X29_XON_XOFF_CODE, 1, /* enable XON/XOFF */ 9845223Ssklower 9945223Ssklower X29_LF_AFTER_CR, 4, /* lf after cr from terminal */ 10045223Ssklower X29_EDITING, 1, /* on */ 10145223Ssklower X29_CHARACTER_DELETE, CERASE, 10245223Ssklower X29_LINE_DELETE, CKILL, 10345223Ssklower X29_LINE_DISPLAY, CRPRNT, 10445223Ssklower 10545223Ssklower /* 10645223Ssklower * This rubbish can be removed when Datapac 10745223Ssklower * adopts the 1980 standard parameter set. 10845223Ssklower */ 10945223Ssklower 11045223Ssklower 0, 0, /* national parameter marker */ 11145223Ssklower 123, 0, /* parity off */ 11245223Ssklower }; 11345223Ssklower 11445223Ssklower struct net { 11545223Ssklower char *n_name; /* generic name */ 11645223Ssklower short n_type; /* see defines above */ 11745223Ssklower char *n_profile; /* initial profile */ 11845223Ssklower short n_proflen; /* length of n_profile */ 11945223Ssklower } *netp, nets[] = { 12045223Ssklower "x.25", X25NET, 0, 0, 12145223Ssklower "1978", CCITT1978, ccitt1978_prof, sizeof(ccitt1978_prof), 12245223Ssklower "ccitt1978", CCITT1978, ccitt1978_prof, sizeof(ccitt1978_prof), 12345223Ssklower "1980", CCITT1980, ccitt1980_prof, sizeof(ccitt1980_prof), 12445223Ssklower "ccitt1980", CCITT1980, ccitt1980_prof, sizeof(ccitt1980_prof), 12545223Ssklower "datapac", CCITT1980, datapac_prof, sizeof(datapac_prof), 12645223Ssklower 0, 0, 0, 0 12745223Ssklower }; 12845223Ssklower 12945223Ssklower main(argc, argv) 13045223Ssklower register char **argv; 13145223Ssklower { 13245223Ssklower register int s, pid; 13345223Ssklower register char *p; 13445223Ssklower 13545223Ssklower /* 13645223Ssklower * If this host doesn't support X.25, give up. 13745223Ssklower */ 13845223Ssklower s = socket(AF_CCITT, SOCK_STREAM, 0); 13945223Ssklower if (s < 0 && errno == EPROTONOSUPPORT) 14045223Ssklower fatal(2, "X.25 is not supported on this machine"); 14145223Ssklower close(s); 14245223Ssklower netp = lookup ("ccitt1978"); 14345223Ssklower sock.x25_family = AF_CCITT; 144*45293Ssklower sock.x25_len = sizeof(sock); 14545223Ssklower sock.x25_opts.op_flags = X25_MQBIT; 14645223Ssklower sock.x25_udata[0] = ITI_CALL; 14745223Ssklower sock.x25_udlen = 4; 14845223Ssklower 14945223Ssklower for (argv++; argc > 1; argc--, argv++) 15045223Ssklower if (**argv == '-') 15145223Ssklower for (p = *argv+1; *p; p++) 15245223Ssklower switch (*p) { 15345223Ssklower case 'b': 15445223Ssklower send_banner++; 15545223Ssklower break; 15645223Ssklower 15745223Ssklower case 'c': 15845223Ssklower if (argc > 1) { 15945223Ssklower argc--; argv++; 16045223Ssklower if ((netp = lookup (*argv)) == 0) 16145223Ssklower fatal(1, "Unknown network type"); 16245223Ssklower } 16345223Ssklower break; 16445223Ssklower 16545223Ssklower case 'p': 16645223Ssklower if (argc > 1) { 16745223Ssklower argc--; argv++; 16845223Ssklower strcpy (sock.x25_udata, *argv); 16945223Ssklower } 17045223Ssklower break; 17145223Ssklower 17245223Ssklower case 'r': 17345223Ssklower sock.x25_opts.op_flags |= X25_REVERSE_CHARGE; 17445223Ssklower break; 17545223Ssklower 176*45293Ssklower case 'd': 177*45293Ssklower debug++; 178*45293Ssklower break; 179*45293Ssklower 18045223Ssklower case 't': 18145223Ssklower if (argc > 1) { 18245223Ssklower argc--; argv++; 18345223Ssklower tracefn = *argv; 18445223Ssklower } 18545223Ssklower else fatal(1, "missing trace file"); 18645223Ssklower break; 18745223Ssklower 18845223Ssklower default: 18945223Ssklower fatal (1, "usage: x29d -b -c nettype -p protocol -r -t trace_file server"); 19045223Ssklower } 19145223Ssklower else 19245223Ssklower server = *argv; 19345223Ssklower if (server == 0) 19445223Ssklower fatal (1, "no server specified"); 195*45293Ssklower if (debug == 0) 196*45293Ssklower daemon(0, 0); 19745223Ssklower 19845223Ssklower while((s = socket(AF_CCITT, SOCK_STREAM, 0)) < 0) 19945223Ssklower sleep(60); 20045223Ssklower while (bind(s, (caddr_t)&sock, sizeof (sock)) < 0) 20145223Ssklower sleep(60); 20245223Ssklower signal(SIGCHLD, reapchild); 20345223Ssklower listen(s, 5); 20445223Ssklower 20545223Ssklower for (;;) { 20645223Ssklower struct sockaddr_x25 from; 20745223Ssklower int fromlen = sizeof (from); 20845223Ssklower 20945223Ssklower if ((net = accept(s, (caddr_t)&from, &fromlen)) < 0) { 21045223Ssklower if (errno != EINTR) 21145223Ssklower sleep (60); 21245223Ssklower continue; 21345223Ssklower } 21445223Ssklower while ((pid = fork()) < 0) 21545223Ssklower sleep(60); 21645223Ssklower if (pid == 0) { 21745223Ssklower signal(SIGCHLD, SIG_DFL); 21845223Ssklower doit(&from); 21945223Ssklower } 22045223Ssklower close(net); 22145223Ssklower } 22245223Ssklower /*NOTREACHED*/ 22345223Ssklower } 22445223Ssklower 22545223Ssklower struct net * 22645223Ssklower lookup (name) 22745223Ssklower char *name; 22845223Ssklower { 22945223Ssklower register struct net *np; 23045223Ssklower 23145223Ssklower for (np = nets; np->n_name; np++) 23245223Ssklower if (strcmp (np->n_name, name) == 0) 23345223Ssklower return (np); 23445223Ssklower return (0); 23545223Ssklower } 23645223Ssklower 23745223Ssklower reapchild() 23845223Ssklower { 23945223Ssklower union wait status; 24045223Ssklower 24145223Ssklower while (wait3(&status, WNOHANG, 0) > 0) 24245223Ssklower ; 24345223Ssklower } 24445223Ssklower 24545223Ssklower char *envinit[] = { "TERM=ccitt", 0 }; 24645223Ssklower int cleanup(); 247*45293Ssklower struct termios term; 24845223Ssklower 24945223Ssklower /* 25045223Ssklower * Get a pty, scan input lines. 25145223Ssklower */ 25245223Ssklower doit(who) 25345223Ssklower struct sockaddr_x25 *who; 25445223Ssklower { 25545223Ssklower register char *cp; 256*45293Ssklower int i, p, t; 25745223Ssklower 25845223Ssklower packet_size = 1 << who->x25_opts.op_psize; 259*45293Ssklower i = forkpty(&pty, line, &term, 0); 260*45293Ssklower if (i > 0) 261*45293Ssklower x29d(); 262*45293Ssklower if (i < 0) 26345223Ssklower fatalperror("fork", errno); 26445223Ssklower environ = envinit; 26545223Ssklower call_server (who); 26645223Ssklower /*NOTREACHED*/ 26745223Ssklower } 26845223Ssklower 26945223Ssklower call_server (who) 27045223Ssklower struct sockaddr_x25 *who; 27145223Ssklower { 27245223Ssklower register struct hostent *hp = 0; 27345223Ssklower register char *p, **ap; 27445223Ssklower char *args[MAXARGS]; 27545223Ssklower struct stat st; 27645223Ssklower struct hostent *getx25hostbyaddr(); 27745223Ssklower int ccitt = 0; 27845223Ssklower 27945223Ssklower p = server; 28045223Ssklower while (*p && *p != ' ' && *p != '\t') /* split program from args */ 28145223Ssklower p++; 28245223Ssklower if (*p) 28345223Ssklower *p++ = '\0'; 28445223Ssklower ap = args; 28545223Ssklower while (*p) { 28645223Ssklower while (*p == ' ' || *p == '\t') 28745223Ssklower p++; 28845223Ssklower if (ap < &args[MAXARGS-2]) 28945223Ssklower *ap++ = p; 29045223Ssklower if (strcmp(p, "-ccitt") == 0) 29145223Ssklower ccitt = 1; 29245223Ssklower while (*p && *p != ' ' && *p != '\t') 29345223Ssklower p++; 29445223Ssklower if (*p) 29545223Ssklower *p++ = '\0'; 29645223Ssklower } 29745223Ssklower if (stat (server, &st) < 0) 29845223Ssklower fatalperror (server, errno); 29945223Ssklower /* 30045223Ssklower * For security: if running as root, switch to user 30145223Ssklower * and group id of server. This prevents privately 30245223Ssklower * maintainted or bogus servers from getting super- 30345223Ssklower * user permissions. 30445223Ssklower */ 30545223Ssklower if (getuid() == 0) { 30645223Ssklower setgid (st.st_gid); 30745223Ssklower setuid (st.st_uid); 30845223Ssklower } 30945223Ssklower if (hp = getx25hostbyaddr (who->x25_addr)) 31045223Ssklower *ap++ = hp->h_name; 31145223Ssklower else 31245223Ssklower *ap++ = (char *)who->x25_addr; 31345223Ssklower /* 31445223Ssklower * If the -ccitt flag was given, add another argument 31545223Ssklower * to tell login if charging is being reversed or not. 31645223Ssklower */ 31745223Ssklower if (ccitt) 31845223Ssklower *ap++ = (who->x25_opts.op_flags & X25_REVERSE_CHARGE) ? "y" : "n"; 31945223Ssklower *ap = 0; 32045223Ssklower execv (server, args); 32145223Ssklower fatalperror (server, errno); 32245223Ssklower /*NOTREACHED*/ 32345223Ssklower } 32445223Ssklower 32545223Ssklower fatal(f, msg) 32645223Ssklower int f; 32745223Ssklower char *msg; 32845223Ssklower { 32945223Ssklower register char *p; 33045223Ssklower char buf[BUFSIZ], *index(); 33145223Ssklower 33245223Ssklower p = buf; 33345223Ssklower if (f == net) 33445223Ssklower *p++ = 0; 33545223Ssklower strcpy(p, "x29d: "); 33645223Ssklower strcat(p, msg); 33745223Ssklower strcat(p, "\n"); 33845223Ssklower (void) write(f, p, (index(p, '\n')-p)+1); 33945223Ssklower exit(1); 34045223Ssklower } 34145223Ssklower 34245223Ssklower fatalperror(msg, err) 34345223Ssklower char *msg; 34445223Ssklower { 34545223Ssklower char buf[BUFSIZ]; 34645223Ssklower extern char *sys_errlist[]; 34745223Ssklower 34845223Ssklower strcpy(buf, msg); 34945223Ssklower strcat(buf, ": "); 35045223Ssklower strcat(buf, sys_errlist[err]); 35145223Ssklower fatal(net, buf); 35245223Ssklower } 35345223Ssklower 35445223Ssklower /* 35545223Ssklower * Main loop. Select from pty and network, and 35645223Ssklower * hand data to iti receiver. 35745223Ssklower */ 35845223Ssklower x29d() 35945223Ssklower { 36045223Ssklower register int pcc, fcc, cc; 36145223Ssklower register char *fbp; 36245223Ssklower int pgrp, x25_interrupt(), on = 1; 36345223Ssklower char hostname[32]; 36445223Ssklower 36545223Ssklower ioctl(net, FIONBIO, (char *)&on); 36645223Ssklower ioctl(pty, FIONBIO, (char *)&on); 36745223Ssklower ioctl(pty, TIOCPKT, (char *)&on); 368*45293Ssklower #define TIOCREMECHO 5 /* to make compile */ 36945223Ssklower ioctl(pty, TIOCREMECHO, (char *)&on); /* enable special pty mode */ 37045223Ssklower signal(SIGPIPE, SIG_IGN); /* why not cleanup? --kwl */ 37145223Ssklower signal(SIGTSTP, SIG_IGN); 37245223Ssklower signal(SIGCHLD, cleanup); 37345223Ssklower signal(SIGHUP, cleanup); 37445223Ssklower 37545223Ssklower signal(SIGTTOU, SIG_IGN); 37645223Ssklower signal(SIGURG, x25_interrupt); /* for out-of-band data */ 37745223Ssklower 37845223Ssklower if (netp->n_proflen) 37945223Ssklower (void) write(net, netp->n_profile, netp->n_proflen); 38045223Ssklower 38145223Ssklower /* 38245223Ssklower * Show banner that getty never gave. 38345223Ssklower */ 38445223Ssklower if (send_banner) { 38545223Ssklower gethostname(hostname, sizeof (hostname)); 38645223Ssklower #ifdef BSD4_3 38745223Ssklower strcpy(pibuf+1, "\r\n\r\n4.3 BSD UNIX ("); 38845223Ssklower #else 38945223Ssklower strcpy(pibuf+1, "\r\n\r\n4.2 BSD UNIX ("); 39045223Ssklower #endif 39145223Ssklower strcat(pibuf+1, hostname); 39245223Ssklower strcat(pibuf+1, ")\r\n\r\n"); 39345223Ssklower pcc = strlen(pibuf+1) + 1; 39445223Ssklower } else 39545223Ssklower pcc = 0; 39645223Ssklower 39745223Ssklower fcc = 0; 39845223Ssklower for (;;) { 39945223Ssklower int ibits, obits; 40045223Ssklower 40145223Ssklower ibits = obits = 0; 40245223Ssklower /* 40345223Ssklower * Never look for input if there's still 40445223Ssklower * stuff in the corresponding output buffer 40545223Ssklower */ 40645223Ssklower if (fcc >= 0) /* net connection alive? */ 40745223Ssklower if (fcc && pcc >= 0) /* output pending? */ 40845223Ssklower obits |= (1 << pty); 40945223Ssklower else 41045223Ssklower if (pcc >= 0) /* pty still alive? */ 41145223Ssklower ibits |= (1 << net); 41245223Ssklower if (pcc >= 0) /* pty connection alive? */ 41345223Ssklower if (pcc && fcc >= 0) /* output pending? */ 41445223Ssklower obits |= (1 << net); 41545223Ssklower else 41645223Ssklower if (fcc >= 0) /* net still alive? */ 41745223Ssklower ibits |= (1 << pty); 41845223Ssklower if(ibits == 0 && obits == 0) 41945223Ssklower break; 42045223Ssklower (void) select(16, &ibits, &obits, (int *)0, 0); 42145223Ssklower if (ibits == 0 && obits == 0) { 42245223Ssklower sleep(5); 42345223Ssklower continue; 42445223Ssklower } 42545223Ssklower 42645223Ssklower /* 42745223Ssklower * Something to read from the network... 42845223Ssklower */ 42945223Ssklower if (ibits & (1 << net)) { 43045223Ssklower fcc = read(net, fibuf, BUFSIZ); 43145223Ssklower fbp = fibuf+1; 43245223Ssklower if (fcc < 0 && errno == EWOULDBLOCK) 43345223Ssklower fcc = 0; 43445223Ssklower else if(fcc <= 0) 43545223Ssklower fcc = -1; 43645223Ssklower else { 43745223Ssklower if (tracefn) 43845223Ssklower x29d_trace("netread", fibuf, fcc); 43945223Ssklower if(fibuf[0] & Q_BIT) { 44045223Ssklower x29_qbit(fcc); 44145223Ssklower fcc = 0; 44245223Ssklower } else 44345223Ssklower fcc--; 44445223Ssklower } 44545223Ssklower } 44645223Ssklower 44745223Ssklower /* 44845223Ssklower * Something to read from the pty... 44945223Ssklower */ 45045223Ssklower if (ibits & (1 << pty)) { 45145223Ssklower pcc = read(pty, pibuf, packet_size+1); 45245223Ssklower if (pcc < 0 && errno == EWOULDBLOCK) 45345223Ssklower pcc = 0; 45445223Ssklower else if (pcc <= 0) 45545223Ssklower pcc = -1; 45645223Ssklower else if(pibuf[0] != 0) { /* non-data packet */ 45745223Ssklower if (pibuf[0] & TIOCPKT_IOCTL) 45845223Ssklower pcc = set_x29_parameters(); 45945223Ssklower else 46045223Ssklower pcc = 0; 46145223Ssklower } else /* data packet */ 46245223Ssklower pibuf[0] = 0; 46345223Ssklower } 46445223Ssklower 46545223Ssklower if ((obits & (1<<net)) && pcc > 0) 46645223Ssklower if((cc = write(net, pibuf, pcc)) == pcc) { 46745223Ssklower if(tracefn) 46845223Ssklower x29d_trace("netwrite", pibuf, pcc); 46945223Ssklower pcc = 0; 47045223Ssklower } else { 47145223Ssklower extern char *sys_errlist[]; 47245223Ssklower 47345223Ssklower if(tracefn) 47445223Ssklower x29d_trace("netwrite", 47545223Ssklower sys_errlist[errno], 47645223Ssklower strlen(sys_errlist[errno])); 47745223Ssklower 47845223Ssklower } 47945223Ssklower 48045223Ssklower if ((obits & (1 << pty)) && fcc > 0) { 48145223Ssklower cc = write(pty, fbp, fcc); 48245223Ssklower if (cc > 0) { 48345223Ssklower fcc -= cc; 48445223Ssklower fbp += cc; 48545223Ssklower } 48645223Ssklower } 48745223Ssklower } 48845223Ssklower cleanup(); 48945223Ssklower } 49045223Ssklower 49145223Ssklower 49245223Ssklower /* 49345223Ssklower * Send interrupt to process on other side of pty. 49445223Ssklower * If it is in raw mode, just write NULL; 49545223Ssklower * otherwise, write intr char. 49645223Ssklower */ 49745223Ssklower 49845223Ssklower x25_interrupt() 49945223Ssklower { 500*45293Ssklower struct termios tt; 50145223Ssklower int zero = 0; 50245223Ssklower 50345223Ssklower signal(SIGURG, x25_interrupt); 504*45293Ssklower tcgetattr(pty, &tt); 505*45293Ssklower if (tt.c_lflag & ISIG) { 506*45293Ssklower tcsetattr(pty, TCSAFLUSH, &tt); 507*45293Ssklower (void) write(pty, &tt.c_cc[VINTR], 1); 508*45293Ssklower } else 50945223Ssklower (void) write(pty, "\0", 1); 51045223Ssklower } 51145223Ssklower 51245223Ssklower cleanup() 51345223Ssklower { 514*45293Ssklower char *p; 51545223Ssklower 516*45293Ssklower p = line + sizeof(_PATH_DEV) - 1; 517*45293Ssklower if (logout(p)) 518*45293Ssklower logwtmp(p, "", ""); 519*45293Ssklower (void)chmod(line, 0666); 520*45293Ssklower (void)chown(line, 0, 0); 521*45293Ssklower *p = 'p'; 522*45293Ssklower (void)chmod(line, 0666); 523*45293Ssklower (void)chown(line, 0, 0); 524*45293Ssklower shutdown(net, 2); 52545223Ssklower exit(1); 52645223Ssklower } 52745223Ssklower 52845223Ssklower /* 52945223Ssklower * Map unix tty modes and special characters 53045223Ssklower * into x29 parameters. 53145223Ssklower */ 53245223Ssklower 53345223Ssklower set_x29_parameters() 53445223Ssklower { 53545223Ssklower register char *p; 53645223Ssklower register int f; 537*45293Ssklower struct termios b; 53845223Ssklower 53945223Ssklower if (netp->n_type == X25NET) 54045223Ssklower return (0); 541*45293Ssklower tcgetattr(pty, &b); 54245223Ssklower p = pibuf; 54345223Ssklower *p++ = Q_BIT; 54445223Ssklower *p++ = X29_SET_PARMS; 545*45293Ssklower /* *p++ = X29_ESCAPE_TO_CMD_CODE; *p++ = (f & (RAW|CBREAK)) == 0;*/ 546*45293Ssklower *p++ = X29_ESCAPE_TO_CMD_CODE; *p++ = (b.c_lflag & ICANON) != 0; 54745223Ssklower 548*45293Ssklower *p++ = X29_ECHO_CODE; *p++ = (b.c_lflag & ECHO) != 0; 549*45293Ssklower *p++ = X29_FORWARDING_SIGNAL_CODE; 550*45293Ssklower *p++ = (b.c_lflag & ISIG) ? 0 : 126; 551*45293Ssklower 55245223Ssklower /* 55345223Ssklower * The value of 10 (0.5 seconds) for the idle timer when 55445223Ssklower * in raw or cbreak mode is a compromise value. For good 55545223Ssklower * interactive response this value should be as low as 55645223Ssklower * possible; for reasonable efficiency with file transfers 55745223Ssklower * this value should be at fairly high. This number should 55845223Ssklower * be changed to suit local requirements. 55945223Ssklower */ 56045223Ssklower 561*45293Ssklower /**p++ = X29_IDLE_TIMER_CODE; *p++ = (f & (RAW|CBREAK)) ? 10 : 0;*/ 562*45293Ssklower *p++ = X29_IDLE_TIMER_CODE; *p++ = (b.c_lflag & ICANON) ? 0 : 10; 563*45293Ssklower 564*45293Ssklower /**p++ = X29_AUX_DEV_CONTROL_CODE;*p++ = (f & TANDEM) != 0;*/ 565*45293Ssklower *p++ = X29_AUX_DEV_CONTROL_CODE;*p++ = (b.c_iflag & IXOFF) != 0; 566*45293Ssklower *p++ = X29_XON_XOFF_CODE; *p++ = (b.c_iflag & IXON) != 0; 56745223Ssklower if(netp->n_type == CCITT1980) { 568*45293Ssklower *p++ = X29_LF_AFTER_CR; 569*45293Ssklower /* *p++ = (f & (RAW|CBREAK) || (f & ECHO) == 0) ? 0 : 4; */ 570*45293Ssklower *p++ = (0 == (b.c_lflag & ICANON) || 0 == (b.c_lflag & ECHO)) ? 571*45293Ssklower 0 : 4; 57245223Ssklower 573*45293Ssklower *p++ = X29_EDITING; *p++ = (b.c_lflag & ICANON) != 0; 574*45293Ssklower #define ctlchar(x) \ 575*45293Ssklower (0 == (b.c_lflag & ICANON) || b.c_cc[x] == _POSIX_VDISABLE) ? 0 : b.c_cc[x] 576*45293Ssklower *p++ = X29_CHARACTER_DELETE; *p++ = ctlchar(VERASE); 577*45293Ssklower *p++ = X29_LINE_DELETE; *p++ = ctlchar(VKILL); 578*45293Ssklower *p++ = X29_LINE_DISPLAY; *p++ = ctlchar(VREPRINT); 57945223Ssklower } 58045223Ssklower return (p - pibuf); 58145223Ssklower } 58245223Ssklower 58345223Ssklower /* 58445223Ssklower * Process Q BIT (control) packets from the net. 58545223Ssklower * The only message that we are interested in are 58645223Ssklower * those indicating output is being discarded. 58745223Ssklower */ 58845223Ssklower 58945223Ssklower x29_qbit(n) 59045223Ssklower { 59145223Ssklower register char *p; 59245223Ssklower 59345223Ssklower switch (fibuf[1]) { 59445223Ssklower case X29_SET_PARMS: 59545223Ssklower case X29_SET_AND_READ_PARMS: 59645223Ssklower case X29_PARAMETER_INDICATION: 59745223Ssklower case X29_INDICATION_OF_BREAK: 59845223Ssklower for(p = &fibuf[2]; p < fibuf+n; p++) { 59945223Ssklower if(*p == X29_TRANSMISSION_SPEED_CODE) { 60045223Ssklower static char speeds[] = { 60145223Ssklower B110, B0, B300, B1200, B600, 60245223Ssklower B0, B0, B0, B0, B0, B0, B0, 60345223Ssklower B2400, B4800, B9600, EXTA }; 604*45293Ssklower struct termios b; 60545223Ssklower 60645223Ssklower if(*++p >= 0 && *p < sizeof(speeds)) { 607*45293Ssklower tcgetattr(pty, &b); 608*45293Ssklower cfsetspeed(&b, speeds[*p]); 609*45293Ssklower tcsetattr(pty, TCSANOW, &b); 61045223Ssklower } 61145223Ssklower } else if(*p == X29_DISCARD_OUTPUT_CODE && *++p != 0) { 61245223Ssklower char message[4]; 61345223Ssklower 61445223Ssklower /* 61545223Ssklower * Always re-enable normal output 61645223Ssklower */ 61745223Ssklower message[0] = Q_BIT; 61845223Ssklower message[1] = X29_SET_PARMS; 61945223Ssklower message[2] = X29_DISCARD_OUTPUT_CODE; 62045223Ssklower message[3] = 0; 62145223Ssklower (void) write(net, message, sizeof(message)); 62245223Ssklower if(tracefn) 62345223Ssklower x29d_trace("netwrite", message, 4); 62445223Ssklower } 62545223Ssklower } 62645223Ssklower return; 62745223Ssklower 62845223Ssklower default: { 62945223Ssklower register char *p2; 63045223Ssklower char buf[BUFSIZ*4]; 63145223Ssklower static int fd; 63245223Ssklower 63345223Ssklower /* 63445223Ssklower * Bad news - we received an x29 error message or 63545223Ssklower * some other unknown packet. Dump the contents 63645223Ssklower * of the packet on the console. 63745223Ssklower */ 63845223Ssklower p = buf; 63945223Ssklower for(p2 = "x29d: unknown q-bit packet: "; *p++ = *p2++; ); 64045223Ssklower for(p2 = fibuf+1; p2 < fibuf+n; p2++) 64145223Ssklower if(*p2 >= ' ' && *p2 < 0177) 64245223Ssklower *p++ = *p2; 64345223Ssklower else { 64445223Ssklower *p++ = '\\'; 64545223Ssklower *p++ = ((*p2 & 0300) >> 6) + '0'; 64645223Ssklower *p++ = ((*p2 & 070) >> 3) + '0'; 64745223Ssklower *p++ = (*p2 & 07) + '0'; 64845223Ssklower } 64945223Ssklower *p++ = '\n'; 65045223Ssklower if(fd <= 0) 65145223Ssklower fd = open(console, 1); 65245223Ssklower (void) write(fd, buf, p-buf); 65345223Ssklower } 65445223Ssklower } 65545223Ssklower } 65645223Ssklower 65745223Ssklower x29d_trace(s, bp, n) 65845223Ssklower char *s, *bp; 65945223Ssklower { 66045223Ssklower static int fd; 66145223Ssklower char buf[BUFSIZ*4]; 66245223Ssklower register char *p1, *p2; 66345223Ssklower 66445223Ssklower for(p1 = buf; *s; *p1++ = *s++); 66545223Ssklower *p1++ = ':'; 66645223Ssklower *p1++ = ' '; 66745223Ssklower for(p2=bp; p2 < bp+n; p2++) 66845223Ssklower if(*p2 >= ' ' && *p2 < 0177) 66945223Ssklower *p1++ = *p2; 67045223Ssklower else { 67145223Ssklower *p1++ = '\\'; 67245223Ssklower *p1++ = ((*p2 & 0300) >> 6) + '0'; 67345223Ssklower *p1++ = ((*p2 & 070) >> 3) + '0'; 67445223Ssklower *p1++ = (*p2 & 07) + '0'; 67545223Ssklower } 67645223Ssklower *p1++ = '\n'; 67745223Ssklower if(fd <= 0) 67845223Ssklower fd = creat(tracefn, 0666); 67945223Ssklower (void) write(fd, buf, p1-buf); 68045223Ssklower } 681