1*32146Sminshall #include <sys/types.h> 2*32146Sminshall #include <sys/socket.h> 3*32146Sminshall #include <sys/time.h> 4*32146Sminshall 5*32146Sminshall #include <errno.h> 6*32146Sminshall 7*32146Sminshall #include <arpa/telnet.h> 8*32146Sminshall 9*32146Sminshall #include "defines.h" 10*32146Sminshall #include "externs.h" 11*32146Sminshall 12*32146Sminshall char netobuf[2*BUFSIZ], *nfrontp, *nbackp; 13*32146Sminshall static char *neturg; /* one past last byte of urgent data */ 14*32146Sminshall 15*32146Sminshall /* 16*32146Sminshall * Initialize internal network data structures. 17*32146Sminshall */ 18*32146Sminshall 19*32146Sminshall init_network() 20*32146Sminshall { 21*32146Sminshall nfrontp = nbackp = netobuf; 22*32146Sminshall NetTrace = stdout; 23*32146Sminshall } 24*32146Sminshall 25*32146Sminshall 26*32146Sminshall /* 27*32146Sminshall * Check to see if any out-of-band data exists on a socket (for 28*32146Sminshall * Telnet "synch" processing). 29*32146Sminshall */ 30*32146Sminshall 31*32146Sminshall int 32*32146Sminshall stilloob(s) 33*32146Sminshall int s; /* socket number */ 34*32146Sminshall { 35*32146Sminshall static struct timeval timeout = { 0 }; 36*32146Sminshall fd_set excepts; 37*32146Sminshall int value; 38*32146Sminshall 39*32146Sminshall do { 40*32146Sminshall FD_ZERO(&excepts); 41*32146Sminshall FD_SET(s, &excepts); 42*32146Sminshall value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); 43*32146Sminshall } while ((value == -1) && (errno == EINTR)); 44*32146Sminshall 45*32146Sminshall if (value < 0) { 46*32146Sminshall perror("select"); 47*32146Sminshall quit(); 48*32146Sminshall } 49*32146Sminshall if (FD_ISSET(s, &excepts)) { 50*32146Sminshall return 1; 51*32146Sminshall } else { 52*32146Sminshall return 0; 53*32146Sminshall } 54*32146Sminshall } 55*32146Sminshall 56*32146Sminshall 57*32146Sminshall /* 58*32146Sminshall * netflush 59*32146Sminshall * Send as much data as possible to the network, 60*32146Sminshall * handling requests for urgent data. 61*32146Sminshall * 62*32146Sminshall * The return value indicates whether we did any 63*32146Sminshall * useful work. 64*32146Sminshall */ 65*32146Sminshall 66*32146Sminshall 67*32146Sminshall int 68*32146Sminshall netflush() 69*32146Sminshall { 70*32146Sminshall int n; 71*32146Sminshall 72*32146Sminshall if ((n = nfrontp - nbackp) > 0) { 73*32146Sminshall if (!neturg) { 74*32146Sminshall n = send(net, nbackp, n, 0); /* normal write */ 75*32146Sminshall } else { 76*32146Sminshall n = neturg - nbackp; 77*32146Sminshall /* 78*32146Sminshall * In 4.2 (and 4.3) systems, there is some question about 79*32146Sminshall * what byte in a sendOOB operation is the "OOB" data. 80*32146Sminshall * To make ourselves compatible, we only send ONE byte 81*32146Sminshall * out of band, the one WE THINK should be OOB (though 82*32146Sminshall * we really have more the TCP philosophy of urgent data 83*32146Sminshall * rather than the Unix philosophy of OOB data). 84*32146Sminshall */ 85*32146Sminshall if (n > 1) { 86*32146Sminshall n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ 87*32146Sminshall } else { 88*32146Sminshall n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ 89*32146Sminshall } 90*32146Sminshall } 91*32146Sminshall } 92*32146Sminshall if (n < 0) { 93*32146Sminshall if (errno != ENOBUFS && errno != EWOULDBLOCK) { 94*32146Sminshall setcommandmode(); 95*32146Sminshall perror(hostname); 96*32146Sminshall NetClose(net); 97*32146Sminshall neturg = 0; 98*32146Sminshall longjmp(peerdied, -1); 99*32146Sminshall /*NOTREACHED*/ 100*32146Sminshall } 101*32146Sminshall n = 0; 102*32146Sminshall } 103*32146Sminshall if (netdata && n) { 104*32146Sminshall Dump('>', nbackp, n); 105*32146Sminshall } 106*32146Sminshall nbackp += n; 107*32146Sminshall if (nbackp >= neturg) { 108*32146Sminshall neturg = 0; 109*32146Sminshall } 110*32146Sminshall if (nbackp == nfrontp) { 111*32146Sminshall nbackp = nfrontp = netobuf; 112*32146Sminshall } 113*32146Sminshall return n > 0; 114*32146Sminshall } 115*32146Sminshall 116*32146Sminshall /* 117*32146Sminshall * nextitem() 118*32146Sminshall * 119*32146Sminshall * Return the address of the next "item" in the TELNET data 120*32146Sminshall * stream. This will be the address of the next character if 121*32146Sminshall * the current address is a user data character, or it will 122*32146Sminshall * be the address of the character following the TELNET command 123*32146Sminshall * if the current address is a TELNET IAC ("I Am a Command") 124*32146Sminshall * character. 125*32146Sminshall */ 126*32146Sminshall 127*32146Sminshall static char * 128*32146Sminshall nextitem(current) 129*32146Sminshall char *current; 130*32146Sminshall { 131*32146Sminshall if ((*current&0xff) != IAC) { 132*32146Sminshall return current+1; 133*32146Sminshall } 134*32146Sminshall switch (*(current+1)&0xff) { 135*32146Sminshall case DO: 136*32146Sminshall case DONT: 137*32146Sminshall case WILL: 138*32146Sminshall case WONT: 139*32146Sminshall return current+3; 140*32146Sminshall case SB: /* loop forever looking for the SE */ 141*32146Sminshall { 142*32146Sminshall register char *look = current+2; 143*32146Sminshall 144*32146Sminshall for (;;) { 145*32146Sminshall if ((*look++&0xff) == IAC) { 146*32146Sminshall if ((*look++&0xff) == SE) { 147*32146Sminshall return look; 148*32146Sminshall } 149*32146Sminshall } 150*32146Sminshall } 151*32146Sminshall } 152*32146Sminshall default: 153*32146Sminshall return current+2; 154*32146Sminshall } 155*32146Sminshall } 156*32146Sminshall /* 157*32146Sminshall * netclear() 158*32146Sminshall * 159*32146Sminshall * We are about to do a TELNET SYNCH operation. Clear 160*32146Sminshall * the path to the network. 161*32146Sminshall * 162*32146Sminshall * Things are a bit tricky since we may have sent the first 163*32146Sminshall * byte or so of a previous TELNET command into the network. 164*32146Sminshall * So, we have to scan the network buffer from the beginning 165*32146Sminshall * until we are up to where we want to be. 166*32146Sminshall * 167*32146Sminshall * A side effect of what we do, just to keep things 168*32146Sminshall * simple, is to clear the urgent data pointer. The principal 169*32146Sminshall * caller should be setting the urgent data pointer AFTER calling 170*32146Sminshall * us in any case. 171*32146Sminshall */ 172*32146Sminshall 173*32146Sminshall static void 174*32146Sminshall netclear() 175*32146Sminshall { 176*32146Sminshall register char *thisitem, *next; 177*32146Sminshall char *good; 178*32146Sminshall #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ 179*32146Sminshall ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) 180*32146Sminshall 181*32146Sminshall thisitem = netobuf; 182*32146Sminshall 183*32146Sminshall while ((next = nextitem(thisitem)) <= nbackp) { 184*32146Sminshall thisitem = next; 185*32146Sminshall } 186*32146Sminshall 187*32146Sminshall /* Now, thisitem is first before/at boundary. */ 188*32146Sminshall 189*32146Sminshall good = netobuf; /* where the good bytes go */ 190*32146Sminshall 191*32146Sminshall while (nfrontp > thisitem) { 192*32146Sminshall if (wewant(thisitem)) { 193*32146Sminshall int length; 194*32146Sminshall 195*32146Sminshall next = thisitem; 196*32146Sminshall do { 197*32146Sminshall next = nextitem(next); 198*32146Sminshall } while (wewant(next) && (nfrontp > next)); 199*32146Sminshall length = next-thisitem; 200*32146Sminshall memcpy(good, thisitem, length); 201*32146Sminshall good += length; 202*32146Sminshall thisitem = next; 203*32146Sminshall } else { 204*32146Sminshall thisitem = nextitem(thisitem); 205*32146Sminshall } 206*32146Sminshall } 207*32146Sminshall 208*32146Sminshall nbackp = netobuf; 209*32146Sminshall nfrontp = good; /* next byte to be sent */ 210*32146Sminshall neturg = 0; 211*32146Sminshall } 212*32146Sminshall 213*32146Sminshall /* 214*32146Sminshall * These routines add various telnet commands to the data stream. 215*32146Sminshall */ 216*32146Sminshall 217*32146Sminshall void 218*32146Sminshall xmitAO() 219*32146Sminshall { 220*32146Sminshall NET2ADD(IAC, AO); 221*32146Sminshall if (autoflush) { 222*32146Sminshall doflush(); 223*32146Sminshall } 224*32146Sminshall } 225*32146Sminshall 226*32146Sminshall 227*32146Sminshall void 228*32146Sminshall xmitEL() 229*32146Sminshall { 230*32146Sminshall NET2ADD(IAC, EL); 231*32146Sminshall } 232*32146Sminshall 233*32146Sminshall void 234*32146Sminshall xmitEC() 235*32146Sminshall { 236*32146Sminshall NET2ADD(IAC, EC); 237*32146Sminshall } 238*32146Sminshall 239*32146Sminshall 240*32146Sminshall #if defined(NOT43) 241*32146Sminshall int 242*32146Sminshall #else /* defined(NOT43) */ 243*32146Sminshall void 244*32146Sminshall #endif /* defined(NOT43) */ 245*32146Sminshall dosynch() 246*32146Sminshall { 247*32146Sminshall netclear(); /* clear the path to the network */ 248*32146Sminshall NET2ADD(IAC, DM); 249*32146Sminshall neturg = NETLOC()-1; /* Some systems are off by one XXX */ 250*32146Sminshall 251*32146Sminshall #if defined(NOT43) 252*32146Sminshall return 0; 253*32146Sminshall #endif /* defined(NOT43) */ 254*32146Sminshall } 255*32146Sminshall 256*32146Sminshall void 257*32146Sminshall doflush() 258*32146Sminshall { 259*32146Sminshall NET2ADD(IAC, DO); 260*32146Sminshall NETADD(TELOPT_TM); 261*32146Sminshall flushline = 1; 262*32146Sminshall flushout = 1; 263*32146Sminshall ttyflush(); 264*32146Sminshall /* do printoption AFTER flush, otherwise the output gets tossed... */ 265*32146Sminshall printoption("<SENT", doopt, TELOPT_TM, 0); 266*32146Sminshall } 267*32146Sminshall 268*32146Sminshall void 269*32146Sminshall intp() 270*32146Sminshall { 271*32146Sminshall NET2ADD(IAC, IP); 272*32146Sminshall if (autoflush) { 273*32146Sminshall doflush(); 274*32146Sminshall } 275*32146Sminshall if (autosynch) { 276*32146Sminshall dosynch(); 277*32146Sminshall } 278*32146Sminshall } 279*32146Sminshall 280*32146Sminshall void 281*32146Sminshall sendbrk() 282*32146Sminshall { 283*32146Sminshall NET2ADD(IAC, BREAK); 284*32146Sminshall if (autoflush) { 285*32146Sminshall doflush(); 286*32146Sminshall } 287*32146Sminshall if (autosynch) { 288*32146Sminshall dosynch(); 289*32146Sminshall } 290*32146Sminshall } 291