pepoとネットワークを語ろう

40年前からこれまでとこれからのネットワークを語る

telnetクライアントへの道その4

2009-07-28 11:12:07 | Linux

/usr/include/arpa/telnet.h の全てコマンドやオプションは対処できませんがLinuxやFreeBSDサーバへログインできるように必要最低限なやり取りを出来るように書きます。

コマンドを受信した時のレスポンス例
| IAC | 動作のタイプ  | オプション |
動作タイプ:Do,Will,Won't,Don't,Sbなど
Command: Do Authentication Option → Command: Won't Authentication Option
Command: Do Encryption Option → Command: Don't Encryption Option
Command: Do Terminal Speed → Command: Won't Terminal Speed
Command: Do X Display Location → Command: Won't X Display Location
Command: Do New Environment Option → Command: Won't New Environment Option
Command: Do Environment Option → Command: Won't Environment Option
Command: Will Suppress Go Ahead → Command: Won't Suppress Go Ahead

殆どの場合、処理不可能なコマンドは動作タイプをWon'tと受信したオプションを付けて返信すればよいことになります

以下のリストは、IACを受信したら次キャラクタの動作タイプを判定しオプションに返送する動作タイプを設定して応答をするようにしています


zmodem_check() { /* zmodem check & telnet option */
  int chh;
  chh = ch & 0377;
  ch3 = chh;
  if ( iac_step_flag != 0 ) {
    if ( iac_step_flag == 1 ) {
      dont_flag = do_flag = will_flag = 0;
      iac_step_flag++;
      switch(chh) {
        case DONT:
          dont_flag = 1;
          break;
        case WILL:
          will_flag = 1;
          break;
        case DO:
          do_flag = 1;
          break;
        case SB:
          sb_flag = 1;
          break;
      }
      return;
    }
    if ( iac_step_flag == 2 ) {
      iac_step_flag = 0;
      display_flag = 1;
      switch(chh) {
        case TELOPT_ECHO:
          if (dont_flag == 1) display_flag = 0;
          if (do_flag == 1) {
            display_flag = 1;
            send_wont_char(ch3);
          }
          if (will_flag == 1) {
            display_flag = 1;
          }
          break;
        case TELOPT_ENCRYPT:
          if (do_flag == 1) send_wont_char(ch3);
          if (will_flag == 1) send_dont_char(ch3);
          break;
        case TELOPT_AUTHENTICATION:
          if (do_flag == 1) send_wont_char(ch3);
          if (will_flag == 1) send_dont_char(ch3);
          break;
        case TELOPT_STATUS:
          if (will_flag == 1 || do_flag == 1) send_wont_char(ch3);
          if (dont_flag == 1) send_dont_char(ch3);
          break;
        case TELOPT_NAWS:
          if (send_window_flag == 1 && do_flag == 1) {
            send_window_size();
          }
          break;
        case TELOPT_TTYPE:
          if (send_ttype_flag == 1 && sb_flag == 1) {
            send_ttype();
          }
          break;
        default:
          if (will_flag == 1) send_dont_char(ch3);
          if (do_flag == 1) send_wont_char(ch3);
          if (send_window_flag == 0) {
            send_will_window();
            send_window_flag = 1;
            send_will_ttype();
            send_ttype_flag = 1;
          }
          break;
      }
      return;
    }
  }


// send telnet option
send_wont_char(ch_send) {
  sprintf(f3,"%c%c%c",IAC,WONT,ch_send);
  write(fp2,&f3,strlen(f3));
 return;
}

send_dont_char(ch_send) {
  sprintf(f3,"%c%c%c",IAC,DONT,ch_send);
  write(fp2,&f3,strlen(f3));
 return;
}

send_will_char(ch_send) {
  sprintf(f3,"%c%c%c",IAC,WILL,ch_send);
  write(fp2,&f3,strlen(f3));
 return;
}

send_will_window() {
  sprintf(f3,"%c%c%c",IAC,WILL,TELOPT_NAWS);
  write(fp2,&f3,strlen(f3));
  return;
}

send_will_ttype() {
  sprintf(f3,"%c%c%c",IAC,WILL,TELOPT_TTYPE);
  write(fp2,&f3,strlen(f3));
  return;
}

send_ttype() {
  int dummy = 0;
  sprintf(f3,"%c%c%c%c%s%c%c",IAC,SB,TELOPT_TTYPE,dummy,MY_TTYPE,IAC,SE);
  write(fp2,&f3, 6 + strlen(MY_TTYPE));
  return;
}

 

pepo