264 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
 * TNET		A server program for MINIX which implements the TCP/IP
 | 
						|
 *		suite of networking protocols.  It is based on the
 | 
						|
 *		TCP/IP code written by Phil Karn et al, as found in
 | 
						|
 *		his NET package for Packet Radio communications.
 | 
						|
 *
 | 
						|
 *		This module handles telnet option processing.
 | 
						|
 *
 | 
						|
 * Author:	Michael Temari, <temari@temari.ae.ge.com>  01/13/93
 | 
						|
 *
 | 
						|
 */
 | 
						|
#include <sys/types.h>
 | 
						|
#include <string.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include "telnetd.h"
 | 
						|
#include "telnet.h"
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#define	IN_DATA	0
 | 
						|
#define	IN_CR	1
 | 
						|
#define	IN_IAC	2
 | 
						|
#define	IN_IAC2	3
 | 
						|
 | 
						|
_PROTOTYPE(static void dowill, (int c));
 | 
						|
_PROTOTYPE(static void dowont, (int c));
 | 
						|
_PROTOTYPE(static void dodo, (int c));
 | 
						|
_PROTOTYPE(static void dodont, (int c));
 | 
						|
_PROTOTYPE(static void respond, (int ack, int option));
 | 
						|
 | 
						|
#define	LASTTELOPT	TELOPT_SGA
 | 
						|
 | 
						|
static int TelROpts[LASTTELOPT+1];
 | 
						|
static int TelLOpts[LASTTELOPT+1];
 | 
						|
 | 
						|
static int telfdout;
 | 
						|
 | 
						|
void tel_init()
 | 
						|
{
 | 
						|
int i;
 | 
						|
 | 
						|
   for(i = 0; i <= LASTTELOPT; i++) {
 | 
						|
	TelROpts[i] = 0;
 | 
						|
	TelLOpts[i] = 0;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
void telopt(fdout, what, option)
 | 
						|
int fdout;
 | 
						|
int what;
 | 
						|
int option;
 | 
						|
{
 | 
						|
char buf[3];
 | 
						|
int len;
 | 
						|
 | 
						|
   buf[0] = IAC;
 | 
						|
   buf[1] = what;
 | 
						|
   buf[2] = option;
 | 
						|
   len = 0;
 | 
						|
 | 
						|
   switch(what) {
 | 
						|
	case DO:
 | 
						|
		if(option <= LASTTELOPT) {
 | 
						|
			TelROpts[option] = 1;
 | 
						|
			len = 3;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case DONT:
 | 
						|
		if(option <= LASTTELOPT) {
 | 
						|
			TelROpts[option] = 1;
 | 
						|
			len = 3;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case WILL:
 | 
						|
		if(option <= LASTTELOPT) {
 | 
						|
			TelLOpts[option] = 1;
 | 
						|
			len = 3;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	case WONT:
 | 
						|
		if(option <= LASTTELOPT) {
 | 
						|
			TelLOpts[option] = 1;
 | 
						|
			len = 3;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
   }
 | 
						|
   if(len > 0)
 | 
						|
	(void) write(fdout, buf, len);
 | 
						|
}
 | 
						|
 | 
						|
int tel_in(fdout, telout, buffer, len)
 | 
						|
int fdout;
 | 
						|
int telout;
 | 
						|
char *buffer;
 | 
						|
int len;
 | 
						|
{
 | 
						|
static int InState = IN_DATA;
 | 
						|
static int ThisOpt = 0;
 | 
						|
char *p;
 | 
						|
char *p2;
 | 
						|
int size;
 | 
						|
int c;
 | 
						|
 | 
						|
   telfdout = telout;
 | 
						|
   p = p2 = buffer;
 | 
						|
   size = 0;
 | 
						|
 | 
						|
   while(len > 0) {
 | 
						|
   	c = (unsigned char)*p++; len--;
 | 
						|
	switch(InState) {
 | 
						|
   		case IN_CR:
 | 
						|
   			InState = IN_DATA;
 | 
						|
   			if(c == 0 || c == '\n')
 | 
						|
   				break;
 | 
						|
   			/* fall through */
 | 
						|
   		case IN_DATA:
 | 
						|
   			if(c == IAC) {
 | 
						|
   				InState = IN_IAC;
 | 
						|
   				break;
 | 
						|
   			}
 | 
						|
   			*p2++ = c; size++;
 | 
						|
   			if(c == '\r') InState = IN_CR;
 | 
						|
   			break;
 | 
						|
   		case IN_IAC:
 | 
						|
   			switch(c) {
 | 
						|
   				case IAC:
 | 
						|
	   				*p2++ = c; size++;
 | 
						|
   					InState = IN_DATA;
 | 
						|
   					break;
 | 
						|
   				case WILL:
 | 
						|
   				case WONT:
 | 
						|
   				case DO:
 | 
						|
   				case DONT:
 | 
						|
   					InState = IN_IAC2;
 | 
						|
   					ThisOpt = c;
 | 
						|
   					break;
 | 
						|
   				case EOR:
 | 
						|
   				case SE:
 | 
						|
   				case NOP:
 | 
						|
   				case BREAK:
 | 
						|
   				case IP:
 | 
						|
   				case AO:
 | 
						|
   				case AYT:
 | 
						|
   				case EC:
 | 
						|
   				case EL:
 | 
						|
   				case GA:
 | 
						|
   				case SB:
 | 
						|
   					break;
 | 
						|
   				default:
 | 
						|
   					break;
 | 
						|
   			}
 | 
						|
   			break;
 | 
						|
   		case IN_IAC2:
 | 
						|
   			if(size > 0) {
 | 
						|
   				write(fdout, buffer, size);
 | 
						|
   				p2 = buffer;
 | 
						|
   				size = 0;
 | 
						|
   			}
 | 
						|
   			InState = IN_DATA;
 | 
						|
   			switch(ThisOpt) {
 | 
						|
   				case WILL:	dowill(c);	break;
 | 
						|
   				case WONT:	dowont(c);	break;
 | 
						|
   				case DO:	dodo(c);	break;
 | 
						|
   				case DONT:	dodont(c);	break;
 | 
						|
   			}
 | 
						|
   			break;
 | 
						|
   	}
 | 
						|
   }
 | 
						|
 | 
						|
   if(size > 0)
 | 
						|
   	write(fdout, buffer, size);
 | 
						|
}
 | 
						|
 | 
						|
int tel_out(fdout, buf, size)
 | 
						|
int fdout;
 | 
						|
char *buf;
 | 
						|
int size;
 | 
						|
{
 | 
						|
char *p;
 | 
						|
int got_iac, len;
 | 
						|
 | 
						|
   p = buf;
 | 
						|
   while(size > 0) {
 | 
						|
	buf = p;
 | 
						|
	got_iac = 0;
 | 
						|
	if((p = (char *)memchr(buf, IAC, size)) != (char *)NULL) {
 | 
						|
		got_iac = 1;
 | 
						|
		p++;
 | 
						|
	} else
 | 
						|
		p = buf + size;
 | 
						|
	len = p - buf;
 | 
						|
	if(len > 0)
 | 
						|
		(void) write(fdout, buf, len);
 | 
						|
	if(got_iac)
 | 
						|
		(void) write(fdout, p - 1, 1);
 | 
						|
	size = size - len;
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
static void dowill(c)
 | 
						|
int c;
 | 
						|
{
 | 
						|
int ack;
 | 
						|
 | 
						|
   switch(c) {
 | 
						|
	case TELOPT_BINARY:
 | 
						|
	case TELOPT_ECHO:
 | 
						|
	case TELOPT_SGA:
 | 
						|
		if(TelROpts[c] == 1)
 | 
						|
			return;
 | 
						|
		TelROpts[c] = 1;
 | 
						|
		ack = DO;
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		ack = DONT;
 | 
						|
   }
 | 
						|
   respond(ack, c);
 | 
						|
}
 | 
						|
 | 
						|
static void dowont(c)
 | 
						|
int c;
 | 
						|
{
 | 
						|
   if(c <= LASTTELOPT) {
 | 
						|
	if(TelROpts[c] == 0)
 | 
						|
		return;
 | 
						|
	TelROpts[c] = 0;
 | 
						|
   }
 | 
						|
   respond(DONT, c);
 | 
						|
}
 | 
						|
 | 
						|
static void dodo(c)
 | 
						|
int c;
 | 
						|
{
 | 
						|
int ack;
 | 
						|
 | 
						|
   switch(c) {
 | 
						|
	default:
 | 
						|
		ack = WONT;
 | 
						|
   }
 | 
						|
   respond(ack, c);
 | 
						|
}
 | 
						|
 | 
						|
static void dodont(c)
 | 
						|
int c;
 | 
						|
{
 | 
						|
   if(c <= LASTTELOPT) {
 | 
						|
	if(TelLOpts[c] == 0)
 | 
						|
		return;
 | 
						|
	TelLOpts[c] = 0;
 | 
						|
   }
 | 
						|
   respond(WONT, c);
 | 
						|
}
 | 
						|
 | 
						|
static void respond(ack, option)
 | 
						|
int ack, option;
 | 
						|
{
 | 
						|
unsigned char c[3];
 | 
						|
 | 
						|
   c[0] = IAC;
 | 
						|
   c[1] = ack;
 | 
						|
   c[2] = option;
 | 
						|
   /* write(telfdout, c, 3); */
 | 
						|
}
 |