Connect using telnet protocol (simple implementation of telnet negotiation) - C#

When the telnet connection, you must first negotiate the communication options. This article implements a simple communication telnet negotiation options to create a login program.

Communication content

Starts sending the client connects to port 23 from the client.
Content of the communication is
IAC WILL terminal_type
IAC DO suppress_go_ahead
IAC WILL suppress_go_ahead
IAC DO echo
IAC WILL window_size
sent.
Wait for a reply from the server after submission. From the server after sending
IAC WILL suppress_go_ahead
IAC DO echo
IAC DO window_size
IAC WILL status
IAC DO remote_flow_control
IAC DO terminal_type
IAC DO suppress_go_ahead
IAC WILL echo
Will be returned.
Tame Hazime cases this will be different from the Telnet server. After the client received from the server.
IAC WONT echo
IAC SB op_window_size 0x00 0x50 0x00 0x18
IAC SE DO echo
IAC DONT status
IAC WONT remote_flow_control
Sent
After sending, 0x0A is returned, it continued to "login:" and "password:" prompt is returned from the server and will wait for login.

Number of command

Number of negotiation command
SE = 0xF0;
NOP = 0xF1;
DM = 0xF2;
BRK = 0xF3;
IP = 0xF4;
AO = 0xF5;
AYT = 0xF6;
EC = 0xF7;
EL = 0xF8;
GA = 0xF9;
SB = 0xFA;
WILL = 0xFB;
WONT = 0xFC;
DO = 0xFD;
DONT = 0xFE;
IAC = 0xFF;
Number of options
suppress_go_ahead = 0x03;
status = 0x05;
echo = 0x01;
timing_mark = 0x06;
terminal_type = 0x18;
window_size = 0x1F;
terminal_speed = 0x20;
remote_flow_control = 0x21;
linemode = 0x22;
environment_variables = 0x24;
As noted above

To examine the contents of communications options for the negotiation

To examine the contents of communications options negotiation, TeraTerm Pro file of teraterm.ini TelLog = on set, TeraTerm TELNET.LOG to connect to the server records the contents of communications options for negotiation.

example

In this program, Yamaha is an example to get administrative privileges will automatically log into the router.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iPentecSocket;

namespace RouterRestart
{
  class Program
  {
    static iPentecSyncClientSocket sock;

    //Telnet Commands
    static byte cmdSE   = 0xF0;
    static byte cmdNOP  = 0xF1;
    static byte cmdDM   = 0xF2;
    static byte cmdBRK  = 0xF3;
    static byte cmdIP   = 0xF4;
    static byte cmdAO   = 0xF5;
    static byte cmdAYT  = 0xF6;
    static byte cmdEC   = 0xF7;
    static byte cmdEL   = 0xF8;
    static byte cmdGA   = 0xF9;
    static byte cmdSB   = 0xFA;

    static byte cmdWILL = 0xFB;
    static byte cmdWONT = 0xFC;
    static byte cmdDO   = 0xFD;
    static byte cmdDONT = 0xFE;
    static byte cmdIAC  = 0xFF;

    //Telnet Options
    static byte op_suppress_go_ahead      = 0x03;
    static byte op_status                 = 0x05;
    static byte op_echo                   = 0x01;
    static byte op_timing_mark            = 0x06;
    static byte op_terminal_type          = 0x18;
    static byte op_window_size            = 0x1F;
    static byte op_terminal_speed         = 0x20;
    static byte op_remote_flow_control    = 0x21;
    static byte op_linemode               = 0x22;
    static byte op_environment_variables  = 0x24;

    static void Main(string[] args)
    {
      sock = new iPentecSyncClientSocket();
      sock.Connect += new iPentecSyncClientSocket.ConnectEventHandler(sock_Connect);
     
      sock.Port = 23;
      sock.Host = "yamaha-router.ipentec.com";
      sock.Timeout = 5000;
      sock.Open();

      byte[] data = new byte[15];
      data[0] = cmdIAC;
      data[1] = cmdWILL;
      data[2] = op_terminal_type;
      data[3] = cmdIAC;
      data[4] = cmdDO;
      data[5] = op_suppress_go_ahead;
      data[6] = cmdIAC;
      data[7] = cmdWILL;
      data[8] = op_suppress_go_ahead;
      data[9] = cmdIAC;
      data[10] = cmdDO;
      data[11] = op_echo;
      data[12] = cmdIAC;
      data[13] = cmdWILL;
      data[14] = op_window_size;
      sock.Write(data);

      int rbytes = sock.Read(out data);
      string recv = DataToString(data, rbytes);
      System.Console.WriteLine(recv);

      data = new byte[3];
      data[0] = cmdIAC;
      data[1] = cmdWONT;
      data[2] = op_echo;
      sock.Write(data);

      data = new byte[11];
      data[0] = cmdIAC;
      data[1] = cmdSB;
      data[2] = op_window_size;
      data[3] = 0x00;
      data[4] = 0x50; //80
      data[5] = 0x00;
      data[6] = 0x18; //24
      data[7] = cmdIAC;
      data[8] = cmdSE;
      data[9] = cmdDO;
      data[10] = op_echo;
      sock.Write(data);

      data = new byte[3];
      data[0] = cmdIAC;
      data[1] = cmdDONT;
      data[2] = op_status;
      sock.Write(data);

      data = new byte[3];
      data[0] = cmdIAC;
      data[1] = cmdWONT;
      data[2] = op_remote_flow_control;
      sock.Write(data);

      data = new byte[1];
      data[0] = 0x0D; //Where the first CR can log in and send you.
      sock.Write(data);

      rbytes = sock.Read(out data);
      recv = DataToString(data, rbytes);
      System.Console.WriteLine(recv);


      //0D 0A Password
      recv = Encoding.ASCII.GetString(data);
      System.Console.WriteLine(recv);
      while (recv.IndexOf("Password") < 0) {
        sock.Read(out data);
        recv = Encoding.ASCII.GetString(data);
      }

      //(If you do not send a CR, the first time fails)
      string cmd = "ROUTER-PASSWORD\r";
      byte[] cmddata = Encoding.ASCII.GetBytes(cmd);
      sock.Write(cmddata);
      
      rbytes = sock.Read(out data);
      recv = Encoding.GetEncoding("SHIFT_JIS").GetString(data);
      System.Console.WriteLine(recv);

      //(CR is not able to log in to send a second time.)
      /*
      sock.Write(cmddata);
      sock.Read(out data);
      recv = Encoding.GetEncoding("SHIFT_JIS").GetString(data);
      System.Console.WriteLine(recv);
      */

      //Wait ">"
      while (recv.IndexOf(">") < 0) {
        sock.Read(out data);
        recv = Encoding.GetEncoding("SHIFT_JIS").GetString(data);
      }
     
      cmd = "administrator\r\n";
      sock.Write(Encoding.ASCII.GetBytes(cmd));

      //Wait "Password"
      rbytes = sock.Read(out data);

      recv = Encoding.GetEncoding("SHIFT_JIS").GetString(data);
      System.Console.WriteLine(recv);
      while (recv.IndexOf("Password") < 0) {
        rbytes = sock.Read(out data);

        recv = Encoding.GetEncoding("SHIFT_JIS").GetString(data);
        System.Console.WriteLine(recv);
      }

      cmd = "ROUTER-ADMINISTRATOR-PASSWORD\r";
      sock.Write(Encoding.ASCII.GetBytes(cmd));

      //Wait "#"
      rbytes = sock.Read(out data);
      
      recv = Encoding.GetEncoding("SHIFT_JIS").GetString(data);
      System.Console.WriteLine(recv);
      while (recv.IndexOf("#") < 0) {
        rbytes = sock.Read(out data);
        
        recv = Encoding.ASCII.GetString(data);
        System.Console.WriteLine(recv);
      }

     //Do something
    }

    static void sock_Send(byte[] SendData)
    {
      //throw new NotImplementedException();
    }

    static void sock_Receive(byte[] ReceiveData)
    {
      //throw new NotImplementedException();
    }

    static string DataToString(byte[] data, int dataBytes)
    {
      string result = "";
      for (int i = 0; i < Math.Min(data.Length, dataBytes); i++)
      {
        result += CmdToString(data[i]) + " ";
      }

      return result;
    }

    static string CmdToString(byte data)
    {
      switch (data)
      {
        case 0xF0:
          return "SE";
          break;
        case 0xF1:
          return "NOP";
          break;
        case 0xF2:
          return "DM";
          break;
        case 0xF3:
          return "BRK";
          break;
        case 0xF4:
          return "IP";
          break;
        case 0xF5:
          return "AO";
          break;
        case 0xF6:
          return "AYT";
          break;
        case 0xF7:
          return "EC";
          break;
        case 0xF8:
          return "EC";
          break;
        case 0xF9:
          return "GA";
          break;
        case 0xFA:
          return "SB";
          break;

        case 0xFB:
          return "WILL";
          break;
        case 0xFC:
          return "WONT";
          break;
        case 0xFD:
          return "DO";
          break;
        case 0xFE:
          return "DONT";
          break;
        case 0xFF:
          return "IAC";
          break;

        case 0x03:
          return "suppress_go_ahead";
          break;
        case 0x05:
          return "status";
          break;
        case 0x01:
          return "echo";
          break;
        case 0x06:
          return "timing_mark";
          break;
        case 0x18:
          return "terminal_type";
          break;
        case 0x1F:
          return "window_size";
          break;
        case 0x20:
          return "terminal_speed";
          break;
        case 0x21:
          return "remote_flow_control";
          break;
        case 0x22:
          return "linemode";
          break;
        case 0x24:
          return "environment_variables";
          break;

        default:
          return "unknown";
          break;
      }

    }

    static void sock_Connect(System.Net.Sockets.Socket client)
    {
      System.Console.WriteLine("Connect");
    }
  }
}

Socket component code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;


namespace iPentecSocket
{
  public partial class iPentecSyncClientSocket : Component
  {
    public iPentecSyncClientSocket()
    {
      InitializeComponent();
    }

    public iPentecSyncClientSocket(IContainer container)
    {
      container.Add(this);

      InitializeComponent();
    }

    private int port = 0;
    private string host = "";
    private int timeout = 0;

    Socket clientSocket = null;

    private static String response = String.Empty;

    private int MAX_BUFFER_SIZE = 2048;

    public enum SocketAction { SA_READ, SA_WRITE, SA_CLOSE, SA_NONE }

    // ecent delegate
    public delegate void ConnectEventHandler(Socket client);
    public delegate void DisconnectEventHandler();
    public delegate void ReceiveEventHandler(byte[] ReceiveData);
    public delegate void SendEventHandler(byte[] SendData);
    //
    public event ConnectEventHandler Connect = null;
    public event DisconnectEventHandler Disconnect = null;
    public event ReceiveEventHandler Receive = null;
    public event SendEventHandler Send = null;

    public int Port
    {
      set { port = value; }
      get { return port; }
    }

    public string Host
    {
      set { host = value; }
      get { return host; }
    }
    
    public int Timeout
    {
      set { timeout = value; }
      get { return timeout; }
    }

    private void DisposedEvent(object sender, EventArgs e)
    {
      Close(clientSocket);
    }

    public void Open()
    {
      try {
        IPHostEntry ipHostInfo = Dns.GetHostEntry(host);

        IPAddress ipAddress = ipHostInfo.AddressList[0];
        //Get IPv4 Address(Get IPv6 addresses that are not)
        for (int i = 0; i < ipHostInfo.AddressList.Length; i++) {
          if (ipHostInfo.AddressList[i].AddressFamily == AddressFamily.InterNetwork) {
            ipAddress = ipHostInfo.AddressList[i];
          }
        }
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

        // Create a TCP/IP  socket.
        clientSocket = new Socket(
          AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        clientSocket.ReceiveTimeout = timeout;

        try {
          clientSocket.Connect(remoteEP);
          if (Connect != null) {
            Connect(clientSocket);
          }
        }
        catch (ArgumentNullException ane) {
          Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
        }
        catch (SocketException se) {
          Console.WriteLine("SocketException : {0}", se.ToString());
        }
        catch (Exception e) {
          Console.WriteLine("Unexpected exception : {0}", e.ToString());
        }
      }
      catch (Exception e) {
        Console.WriteLine(e.ToString());
      }

    }

    public void Close(Socket client)
    {
      clientSocket.Shutdown(SocketShutdown.Both);
      clientSocket.Close();

      if (Disconnect != null) {
        Close(clientSocket);
      }
    }

    public int Read(out byte[] bytes)
    {
      // Receive the response from the remote device.
      bytes = new byte[MAX_BUFFER_SIZE];

      int bytesReceive = clientSocket.Receive(bytes,SocketFlags.None);
      if (Receive != null) {
        Receive(bytes);
      }
      return bytesReceive;
    }

    public void Read(out byte[] bytes, out int bytesReceive)
    {
      bytesReceive = Read(out bytes);
    }

    public int Write(byte[] data, int bytesWrite)
    {
      int bytesRec = clientSocket.Send(data,bytesWrite,SocketFlags.None);

      if (Send != null) {
        Send(data);
      }
      return bytesRec;
    }

    public int Write(byte[] data)
    {
      int bytesRec = clientSocket.Send(data, SocketFlags.None);
      if (Send != null)
      {
        Send(data);
      }
      return bytesRec;
    }
  }
}
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2024-01-06
作成日: 2011-10-20
iPentec all rights reserverd.