132146Sminshall #include <sys/types.h> 232146Sminshall #include <sys/socket.h> 332146Sminshall #include <sys/time.h> 432146Sminshall 532146Sminshall #include <errno.h> 632146Sminshall 732146Sminshall #include <arpa/telnet.h> 832146Sminshall 932381Sminshall #include "ring.h" 1032381Sminshall 1132146Sminshall #include "defines.h" 1232146Sminshall #include "externs.h" 1332146Sminshall 14*32531Sminshall Ring netoring, netiring; 15*32531Sminshall char netobuf[2*BUFSIZ], netibuf[BUFSIZ]; 1632146Sminshall 1732146Sminshall /* 1832146Sminshall * Initialize internal network data structures. 1932146Sminshall */ 2032146Sminshall 2132146Sminshall init_network() 2232146Sminshall { 2332381Sminshall ring_init(&netoring, netobuf, sizeof netobuf); 24*32531Sminshall ring_init(&netiring, netibuf, sizeof netibuf); 2532146Sminshall NetTrace = stdout; 2632146Sminshall } 2732146Sminshall 2832146Sminshall 2932146Sminshall /* 3032146Sminshall * Check to see if any out-of-band data exists on a socket (for 3132146Sminshall * Telnet "synch" processing). 3232146Sminshall */ 3332146Sminshall 3432146Sminshall int 3532146Sminshall stilloob(s) 3632146Sminshall int s; /* socket number */ 3732146Sminshall { 3832146Sminshall static struct timeval timeout = { 0 }; 3932146Sminshall fd_set excepts; 4032146Sminshall int value; 4132146Sminshall 4232146Sminshall do { 4332146Sminshall FD_ZERO(&excepts); 4432146Sminshall FD_SET(s, &excepts); 4532146Sminshall value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); 4632146Sminshall } while ((value == -1) && (errno == EINTR)); 4732146Sminshall 4832146Sminshall if (value < 0) { 4932146Sminshall perror("select"); 5032146Sminshall quit(); 5132146Sminshall } 5232146Sminshall if (FD_ISSET(s, &excepts)) { 5332146Sminshall return 1; 5432146Sminshall } else { 5532146Sminshall return 0; 5632146Sminshall } 5732146Sminshall } 5832146Sminshall 5932146Sminshall 6032146Sminshall /* 6132257Sminshall * setneturg() 6232257Sminshall * 6332257Sminshall * Sets "neturg" to the current location. 6432257Sminshall */ 6532257Sminshall 6632257Sminshall void 6732257Sminshall setneturg() 6832257Sminshall { 6932381Sminshall ring_mark(&netoring); 7032257Sminshall } 7132257Sminshall 7232257Sminshall 7332257Sminshall /* 7432146Sminshall * netflush 7532146Sminshall * Send as much data as possible to the network, 7632146Sminshall * handling requests for urgent data. 7732146Sminshall * 7832146Sminshall * The return value indicates whether we did any 7932146Sminshall * useful work. 8032146Sminshall */ 8132146Sminshall 8232146Sminshall 8332146Sminshall int 8432146Sminshall netflush() 8532146Sminshall { 8632146Sminshall int n; 8732146Sminshall 8832528Sminshall if ((n = ring_full_consecutive(&netoring)) > 0) { 8932381Sminshall if (!ring_at_mark(&netoring)) { 9032528Sminshall n = send(net, netoring.consume, n, 0); /* normal write */ 9132146Sminshall } else { 9232146Sminshall /* 9332146Sminshall * In 4.2 (and 4.3) systems, there is some question about 9432146Sminshall * what byte in a sendOOB operation is the "OOB" data. 9532146Sminshall * To make ourselves compatible, we only send ONE byte 9632146Sminshall * out of band, the one WE THINK should be OOB (though 9732146Sminshall * we really have more the TCP philosophy of urgent data 9832146Sminshall * rather than the Unix philosophy of OOB data). 9932146Sminshall */ 10032528Sminshall n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */ 10132146Sminshall } 10232146Sminshall } 10332146Sminshall if (n < 0) { 10432146Sminshall if (errno != ENOBUFS && errno != EWOULDBLOCK) { 10532146Sminshall setcommandmode(); 10632146Sminshall perror(hostname); 10732146Sminshall NetClose(net); 10832381Sminshall ring_clear_mark(&netoring); 10932146Sminshall longjmp(peerdied, -1); 11032146Sminshall /*NOTREACHED*/ 11132146Sminshall } 11232146Sminshall n = 0; 11332146Sminshall } 11432146Sminshall if (netdata && n) { 11532528Sminshall Dump('>', netoring.consume, n); 11632146Sminshall } 11732528Sminshall ring_consumed(&netoring, n); 11832146Sminshall return n > 0; 11932146Sminshall } 12032146Sminshall 12132146Sminshall /* 12232146Sminshall * nextitem() 12332146Sminshall * 12432146Sminshall * Return the address of the next "item" in the TELNET data 12532146Sminshall * stream. This will be the address of the next character if 12632146Sminshall * the current address is a user data character, or it will 12732146Sminshall * be the address of the character following the TELNET command 12832146Sminshall * if the current address is a TELNET IAC ("I Am a Command") 12932146Sminshall * character. 13032146Sminshall */ 13132146Sminshall 13232146Sminshall static char * 13332146Sminshall nextitem(current) 13432146Sminshall char *current; 13532146Sminshall { 13632146Sminshall if ((*current&0xff) != IAC) { 13732146Sminshall return current+1; 13832146Sminshall } 13932146Sminshall switch (*(current+1)&0xff) { 14032146Sminshall case DO: 14132146Sminshall case DONT: 14232146Sminshall case WILL: 14332146Sminshall case WONT: 14432146Sminshall return current+3; 14532146Sminshall case SB: /* loop forever looking for the SE */ 14632146Sminshall { 14732146Sminshall register char *look = current+2; 14832146Sminshall 14932146Sminshall for (;;) { 15032146Sminshall if ((*look++&0xff) == IAC) { 15132146Sminshall if ((*look++&0xff) == SE) { 15232146Sminshall return look; 15332146Sminshall } 15432146Sminshall } 15532146Sminshall } 15632146Sminshall } 15732146Sminshall default: 15832146Sminshall return current+2; 15932146Sminshall } 16032146Sminshall } 16132381Sminshall 16232146Sminshall /* 16332146Sminshall * netclear() 16432146Sminshall * 16532146Sminshall * We are about to do a TELNET SYNCH operation. Clear 16632146Sminshall * the path to the network. 16732146Sminshall * 16832146Sminshall * Things are a bit tricky since we may have sent the first 16932146Sminshall * byte or so of a previous TELNET command into the network. 17032146Sminshall * So, we have to scan the network buffer from the beginning 17132146Sminshall * until we are up to where we want to be. 17232146Sminshall * 17332146Sminshall * A side effect of what we do, just to keep things 17432146Sminshall * simple, is to clear the urgent data pointer. The principal 17532146Sminshall * caller should be setting the urgent data pointer AFTER calling 17632146Sminshall * us in any case. 17732146Sminshall */ 17832146Sminshall 17932257Sminshall void 18032146Sminshall netclear() 18132146Sminshall { 18232381Sminshall #if 0 /* XXX */ 18332146Sminshall register char *thisitem, *next; 18432146Sminshall char *good; 18532146Sminshall #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ 18632146Sminshall ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) 18732146Sminshall 18832146Sminshall thisitem = netobuf; 18932146Sminshall 19032381Sminshall while ((next = nextitem(thisitem)) <= netobuf.send) { 19132146Sminshall thisitem = next; 19232146Sminshall } 19332146Sminshall 19432146Sminshall /* Now, thisitem is first before/at boundary. */ 19532146Sminshall 19632146Sminshall good = netobuf; /* where the good bytes go */ 19732146Sminshall 19832381Sminshall while (netoring.add > thisitem) { 19932146Sminshall if (wewant(thisitem)) { 20032146Sminshall int length; 20132146Sminshall 20232146Sminshall next = thisitem; 20332146Sminshall do { 20432146Sminshall next = nextitem(next); 20532146Sminshall } while (wewant(next) && (nfrontp > next)); 20632146Sminshall length = next-thisitem; 20732146Sminshall memcpy(good, thisitem, length); 20832146Sminshall good += length; 20932146Sminshall thisitem = next; 21032146Sminshall } else { 21132146Sminshall thisitem = nextitem(thisitem); 21232146Sminshall } 21332146Sminshall } 21432146Sminshall 21532381Sminshall #endif /* 0 */ 21632381Sminshall ring_init(&netoring, netobuf, sizeof netobuf); 21732146Sminshall } 21832381Sminshall 21932381Sminshall #include <varargs.h> 22032381Sminshall 22132381Sminshall void 22232381Sminshall netoprint(va_alist) 22332381Sminshall va_dcl 22432381Sminshall { 22532381Sminshall va_list ap; 22632381Sminshall char buffer[100]; /* where things go */ 22732382Sminshall char *ptr; 22832381Sminshall char *format; 22932382Sminshall char *string; 23032381Sminshall int i; 23132381Sminshall 23232381Sminshall va_start(ap); 23332381Sminshall 23432381Sminshall format = va_arg(ap, char *); 23532382Sminshall ptr = buffer; 23632381Sminshall 23732381Sminshall while ((i = *format++) != 0) { 23832381Sminshall if (i == '%') { 23932381Sminshall i = *format++; 24032381Sminshall switch (i) { 24132381Sminshall case 'c': 24232382Sminshall *ptr++ = va_arg(ap, int); 24332381Sminshall break; 24432382Sminshall case 's': 24532382Sminshall string = va_arg(ap, char *); 24632528Sminshall ring_supply_data(&netoring, buffer, ptr-buffer); 24732528Sminshall ring_supply_data(&netoring, string, strlen(string)); 24832382Sminshall ptr = buffer; 24932382Sminshall break; 25032381Sminshall case 0: 25132382Sminshall ExitString("netoprint: trailing %%.\n", 1); 25232381Sminshall /*NOTREACHED*/ 25332381Sminshall default: 25432381Sminshall ExitString("netoprint: unknown format character.\n", 1); 25532381Sminshall /*NOTREACHED*/ 25632381Sminshall } 25732381Sminshall } else { 25832381Sminshall *ptr++ = i; 25932381Sminshall } 26032381Sminshall } 26132528Sminshall ring_supply_data(&netoring, buffer, ptr-buffer); 26232381Sminshall } 263