Example #1
0
/*---------------------------------------------------------------------------*/
static void
newdata(void)
{
  u16_t len;
  u8_t c;
  char *dataptr;
    
  
  len = uip_datalen();
  dataptr = (char *)uip_appdata;
  
  while(len > 0 && s.bufptr < sizeof(s.buf)) {
    c = *dataptr;
    ++dataptr;
    --len;
    switch(s.state) {
    case STATE_IAC:
      if(c == TELNET_IAC) {
	get_char(c);
	s.state = STATE_NORMAL;
      } else {
	switch(c) {
	case TELNET_WILL:
	  s.state = STATE_WILL;
	  break;
	case TELNET_WONT:
	  s.state = STATE_WONT;
	  break;
	case TELNET_DO:
	  s.state = STATE_DO;
	  break;
	case TELNET_DONT:
	  s.state = STATE_DONT;
	  break;
	default:
	  s.state = STATE_NORMAL;
	  break;
	}
      }
      break;
    case STATE_WILL:
      /* Reply with a DONT */
      sendopt(TELNET_DONT, c);
      s.state = STATE_NORMAL;
      break;
      
    case STATE_WONT:
      /* Reply with a DONT */
      sendopt(TELNET_DONT, c);
      s.state = STATE_NORMAL;
      break;
    case STATE_DO:
      /* Reply with a WONT */
      sendopt(TELNET_WONT, c);
      s.state = STATE_NORMAL;
      break;
    case STATE_DONT:
      /* Reply with a WONT */
      sendopt(TELNET_WONT, c);
      s.state = STATE_NORMAL;
      break;
    case STATE_NORMAL:
      if(c == TELNET_IAC) {
	s.state = STATE_IAC;
      } else {
	get_char(c);
      }
      break;
    }

    
  }
  
}
Example #2
0
/*---------------------------------------------------------------------------*/
static void
newdata(void)
{
  u16_t len;
  u8_t c;
  uint8_t *ptr;
    
  len = uip_datalen();
  PRINTF("newdata len %d '%.*s'\n", len, len, (char *)uip_appdata);

  ptr = uip_appdata;
  while(len > 0 && s.bufptr < sizeof(s.buf)) {
    c = *ptr;
    PRINTF("newdata char '%c' %d %d state %d\n", c, c, len, s.state);
    ++ptr;
    --len;
    switch(s.state) {
    case STATE_IAC:
      if(c == TELNET_IAC) {
	get_char(c);
	s.state = STATE_NORMAL;
      } else {
	switch(c) {
	case TELNET_WILL:
	  s.state = STATE_WILL;
	  break;
	case TELNET_WONT:
	  s.state = STATE_WONT;
	  break;
	case TELNET_DO:
	  s.state = STATE_DO;
	  break;
	case TELNET_DONT:
	  s.state = STATE_DONT;
	  break;
	default:
	  s.state = STATE_NORMAL;
	  break;
	}
      }
      break;
    case STATE_WILL:
      /* Reply with a DONT */
      sendopt(TELNET_DONT, c);
      s.state = STATE_NORMAL;
      break;
      
    case STATE_WONT:
      /* Reply with a DONT */
      sendopt(TELNET_DONT, c);
      s.state = STATE_NORMAL;
      break;
    case STATE_DO:
      /* Reply with a WONT */
      sendopt(TELNET_WONT, c);
      s.state = STATE_NORMAL;
      break;
    case STATE_DONT:
      /* Reply with a WONT */
      sendopt(TELNET_WONT, c);
      s.state = STATE_NORMAL;
      break;
    case STATE_NORMAL:
      if(c == TELNET_IAC) {
	s.state = STATE_IAC;
      } else {
	get_char(c);
      }
      break;
    }
  }
}
Example #3
0
File: tcp.c Project: esirola/powwow
/*
 * read a maximum of size chars from remote host
 * using the telnet protocol. return chars read.
 */
int tcp_read __P3 (int,fd, char *,buffer, int,maxsize)
{
    char state = CONN_LIST(fd).state;
    int i;
    static byte subopt[MAX_SUBOPT];
    static int subchars;
    byte *p, *s, *linestart;
    
    while ((i = read(fd, buffer, maxsize)) < 0 && errno == EINTR)
	;
    
    if (i == 0) {
	CONN_LIST(fd).state = NORMAL;
	tcp_close(NULL);
	return 0;
    }
    if (i < 0) {
	errmsg("read from socket");
	return 0;
    }
    
    /*
     * scan through the buffer,
     * interpret telnet protocol escapes and MUME MPI messages
     */
    for (s = p = linestart = (byte *)buffer; i; s++, i--) {
	switch (state) {
	 case NORMAL:
	 case ALTNORMAL:
	 case GOT_R:
	 case GOT_N:
	    /*
	     * Some servers like to send NULs and other funny chars.
	     * Clean up as much as possible.
	     */
	    switch (*s) {
	     case IAC:
		state = GOTIAC;
		break;
	     case '\r':
		/* start counting \r, unless just got \n */
		if (state == NORMAL || state == ALTNORMAL) {
		    /*
		     * ALTNORMAL is safe here: \r cannot be in MPI header,
		     * and any previous MPI header has already been rejected
		     */
		    state = GOT_R;
		} else if (state == GOT_N)
		  /* after \n\r, we forbid MPI messages */
		    state = ALTNORMAL;
		break;
	     case '\n':
		state = GOT_N;
		*p++ = *s;
		linestart = p;
		break;
	     case '\0':
		/* skip NULs */
		break;
	     default:
		/* first, flush any missing \r */
		if (state == GOT_R)
		  *p++ = '\r';
		
		*p++ = *s;
		
		/* check for MUME MPI messages: */
		if (p - linestart == MPILEN && !memcmp(linestart, MPI, MPILEN)) {
		    if (!(CONN_LIST(fd).flags & IDEDITOR)) {
			PRINTF("#warning: MPI message received without #request editor!\n");
		    } else if (state == ALTNORMAL) {
			/* no MPI messages after \n\r */
			PRINTF("#warning: MPI attack?\n");
		    } else {
			subchars = process_message((char*)s+1, i-1);
			/* no +MPILEN here, as it was already processed. */
			s += subchars; i-= subchars;
			p = linestart;
		    }
		}
		
		if (state != ALTNORMAL)
		    state = NORMAL;
		break;
	    }
	    break;
	    
	 case GOTIAC:
	    switch (*s) {
	     case WILL:
		state = GOTWILL; break;
	     case WONT:
		state = GOTWONT; break;
	     case DO:
		state = GOTDO; break;
	     case DONT:
		state = GOTDONT; break;
	     case SB:		/* BUG (multiple connections):	*/
		state = GOTSB;	/* there is only one subopt buffer */
		subchars = 0;
		break;
	     case IAC:
		*p++ = IAC;
		state = NORMAL;
		break;
	     case GA:
		/* I should handle GA as end-of-prompt marker one day */
		/* one day has come ;) - Max */
		prompt_set_iac((char*)p);
		state = NORMAL;
		break;
	     default:
		/* ignore the rest of the telnet commands */
#ifdef TELOPTS
		tty_printf("[skipped IAC <%d>]\n", *s);
#endif
		state = NORMAL;
		break;
	    }
	    break;
	    
	 case GOTWILL:
#ifdef TELOPTS
	    tty_printf("[got WILL %s]\n", TELOPTSTR(*s));
#endif
	    switch(*s) {
	     case TELOPT_ECHO:
		/* host echoes, turn off echo here
		 * but only for main connection, since we do not want
		 * subsidiary connection password entries to block anything
		 * in the main connection
		 */
		if (fd == tcp_main_fd)
		    linemode |= LM_NOECHO;
		sendopt(DO, *s);
		break;
	     case TELOPT_SGA:
		/* this can't hurt */
		linemode |= LM_CHAR;
		tty_special_keys();
		sendopt(DO, *s);
		break;
	     default:
		/* don't accept other options */
		sendopt(DONT, *s);
		break;
	    }
	    state = NORMAL;
	    break;
	    
	 case GOTWONT:
#ifdef TELOPTS
	    tty_printf("[got WONT %s]\n", TELOPTSTR(*s));
#endif
	    if (*s == TELOPT_ECHO) {
		/* host no longer echoes, we do it instead */
		linemode &= ~LM_NOECHO;
	    }
	    /* accept any WONT */
	    sendopt(DONT, *s);
	    state = NORMAL;
	    break;
	    
	 case GOTDO:
#ifdef TELOPTS
	    tty_printf("[got DO %s]\n", TELOPTSTR(*s));
#endif
	    switch(*s) {
	     case TELOPT_SGA:
		linemode |= LM_CHAR;
		tty_special_keys();
		/* FALLTHROUGH */
	     case TELOPT_TTYPE:
		sendopt(WILL, *s);
		break;
	     case TELOPT_NAWS:
		sendopt(WILL, *s);
		tcp_write_tty_size();
		break;
	     default:
		/* accept nothing else */
		sendopt(WONT, *s);
		break;
	    }
	    state = NORMAL;
	    break;
	    
	 case GOTDONT:
#ifdef TELOPTS
	    tty_printf("[got DONT %s]\n", TELOPTSTR(*s));
#endif
	    if (*s == TELOPT_SGA) {
		linemode &= ~LM_CHAR;
		tty_special_keys();
	    }
	    sendopt(WONT, *s);
	    state = NORMAL;
	    break;
	    
	 case GOTSB:
	    if (*s == IAC) {
		state = GOTSBIAC;
	    } else {
		if (subchars < MAX_SUBOPT)
		  subopt[subchars++] = *s;
	    }
	    break;
	    
	 case GOTSBIAC:
	    if (*s == IAC) {
		if (subchars < MAX_SUBOPT)
		  subopt[subchars++] = IAC;
		state = GOTSB;
	    } else if (*s == SE) {
		subopt[subchars] = '\0';
		dosubopt(subopt);
		state = NORMAL;
	    } else {
		/* problem! I haven't the foggiest idea of what to do here.
		 * I'll just ignore it and hope it goes away. */
		PRINTF("#telnet: got IAC <%d> instead of IAC SE!\n", (int)*s);
		state = NORMAL;
	    }
	    break;
	}
    }
    CONN_LIST(fd).state = state;
    
    if (!(CONN_LIST(tcp_fd).flags & SPAWN)) {
        log_write(buffer, (char *)p - buffer, 0);
    }
    
    return (char *)p - buffer;
}