// all telnet negotiation options supported, some do not follow the DO-WILL-DONT-WONT
static int check_telopts(DESCRIPTOR_DATA *d, char *soin, int i, int *length) {
unsigned char iac_type, iac_command;
int j = 0, l = 0, len = *length;
if( (unsigned char)soin[i] == IAC ) {
i++;
iac_type = soin[i++];
switch( iac_type ) {
case DO: // do attempt to negotiate, or client does support
iac_command = soin[i++];
if( iac_command == TELOPT_BINARY ) {
write_to_descriptor(d, wont_binary_str, 0);
} else if( iac_command == TELOPT_ECHO ) {
SET_BIT(d->telOpts, 7); // putty sends this automatically
// we will not echo characters, may be bandwith problems
} else if( iac_command == TELOPT_OUTMRK ) {
if( !IS_SET(d->telOpts, 10) ) {
char out[SHORT_STR_LENGTH];
strcpy(out, neg_outmrk_start);
strcat(out, "The Breeding Grounds");
strcat(out, neg_outmrk_end);
write_to_descriptor(d, out, 0);
}
SET_BIT(d->telOpts, 10);
} else if( iac_command == TELOPT_COMPRESS2 ) {
if( !IS_SET(d->telOpts, 3) )
write_to_buffer(d, "Compression supported.\r\n");
compressStart(d);
} else if( iac_command == TELOPT_SGA ) {
SET_BIT(d->telOpts, 5); // putty sends this automatically
} else
bug("Unsupported IAC DO command %x.", iac_command);
break;
case WILL: // client will negotiate, or client wants
iac_command = soin[i++];
if( iac_command == TELOPT_BINARY ) {
write_to_descriptor(d, dont_binary_str, 0);
} else if( iac_command == TELOPT_ECHO ) {
SET_BIT(d->telOpts, 7);
bug("Implement WILL ECHO bitches!");
} else if( iac_command == TELOPT_TTYPE ) {
SET_BIT(d->telOpts, 0); //supports telnet type
if( !IS_SET(d->telOpts, 15) )
write_to_descriptor(d, neg_term_type_str, 0);
} else if( iac_command == TELOPT_TUID ) {
if( !IS_SET(d->telOpts, 14) )
write_to_descriptor(d, do_tuid_str, 0);
} else if( iac_command == TELOPT_NAWS ) {
if( !IS_SET(d->telOpts, 1) )
write_to_descriptor(d, neg_naws_str, 0);
SET_BIT(d->telOpts, 1);
} else if( iac_command == TELOPT_LINEMODE ) {
SET_BIT(d->telOpts, 4);
bug("Implement WILL LINEMODE bitches!");
} else if( iac_command == TELOPT_SGA ) {
SET_BIT(d->telOpts, 5);
} else if( iac_command == TELOPT_SPEED ) {
SET_BIT(d->telOpts, 6); // GO PUTTY!
write_to_descriptor(d, dont_tspeed_str, 0);
} else if( iac_command == TELOPT_ENVIRON ) {
write_to_descriptor(d, dont_oldenv_str, 0);
} else if( iac_command == TELOPT_NEWENV ) {
write_to_descriptor(d, dont_newenv_str, 0);
} else
bug("Unsupported IAC WILL command %x.", iac_command);
break;
case DONT: // client does not want
iac_command = soin[i++];
if( iac_command == TELOPT_COMPRESS2 ) {
REMOVE_BIT(d->telOpts, 3);
compressEnd(d);
} else if( iac_command == TELOPT_OUTMRK ) {
REMOVE_BIT(d->telOpts, 10);
} else
bug("Unsupported IAC DONT command %x.", iac_command);
break;
case WONT: // client does not support
iac_command = soin[i++];
if( iac_command == TELOPT_SGA ) {
write_to_buffer(d, "Half-Duplex connections are not supported.\r\n");
close_socket(d, FALSE);
} else if( iac_command == TELOPT_TUID ) {
REMOVE_BIT(d->telOpts, 14);
} else if( iac_command == TELOPT_TTYPE ) {
write_to_buffer(d, "Client does not support terminal type negotiation, ANSI color disabled.\r\n");
REMOVE_BIT(d->telOpts, 0);
REMOVE_BIT(d->telOpts, 15);
} else if( iac_command == TELOPT_NAWS ) {
REMOVE_BIT(d->telOpts, 1); // Pueblo does not support
} else if( iac_command == TELOPT_LINEMODE ) {
REMOVE_BIT(d->telOpts, 2); // Pueblo does not support
} else if( iac_command == TELOPT_ECHO ) {
REMOVE_BIT(d->telOpts, 7);
} else
bug("Unsupported IAC WONT command %x.", iac_command);
break;
case SB: // subnegotiation
iac_command = soin[i++];
if( iac_command == TELOPT_TTYPE ) {
// should be implemented without fault
char ttype[24]; // should be well long enough for this
j = 0;
// blitz thru until we find ascii characters
while( !isprint(soin[i]) ) i++;
while( isprint(soin[i]) ) {
ttype[j] = LOWER(soin[i]);
i++; j++;
}
ttype[j] = '\0';
j = 0;
while( supported_ansi[j] != NULL ) {
if( strcmp(ttype, supported_ansi[j]) == 0 ) {
if( !IS_SET(d->telOpts, 15) ) {
SET_BIT(d->telOpts, 15);
write_to_buffer(d, "&G&uA&bN&yS&rI&& Color supported.\r\n");
}
break;
}
j++;
}
if( !IS_SET(d->telOpts, 15) ) { // only asks twice
if( !IS_SET(d->nextOpt, 15) ) {
write_to_descriptor(d, neg_term_type_str, 0);
SET_BIT(d->nextOpt, 15);
} else { // no support for color
REMOVE_BIT(d->nextOpt, 15);
REMOVE_BIT(d->telOpts, 15);
}
}
} else if( iac_command == TELOPT_TUID ) {
// use this instead of username/password
unsigned long uuid = 0L;
unsigned char tmp;
SET_BIT(d->telOpts, 14);
tmp = soin[i++];
if( tmp > 0 ) {
if( tmp == 255 ) tmp = soin[i++];
uuid += (tmp << 24);
}
tmp = soin[i++];
if( tmp > 0 ) {
if( tmp == 255 ) tmp = soin[i++];
uuid += (tmp << 16);
}
tmp = soin[i++];
if( tmp > 0 ) {
if( tmp == 255 ) tmp = soin[i++];
uuid += (tmp << 8);
}
tmp = soin[i++];
if( tmp > 0 && tmp == 255 ) tmp = soin[i++];
uuid += tmp;
if( uuid <= 0 ) {
write_to_buffer(d, "UUID less than or equal to ZERO not supported.\r\n");
close_socket(d, FALSE);
break;
}
d->uniqueNumber = uuid;
} else if( iac_command == TELOPT_NAWS ) {
|