Search code examples
c++telnetwinsock

C++ WinSock sending commands to telnet server


So I'm making a C++ program that connects through telnet. The connection seems to be working, because I get output from the server. The problem is that I need to send a specific command to telnet. For example a command:

login user password

Just sending it via send() doesn't seem to do anything (or maybe I'm doing something wrong, but don't see it). There are some information on the page ftp://ftp.rfc-editor.org/in-notes/rfc854.txt but I don't really understand it.

Can someone show me on an example and explain how should I do it to make it work? Tried to google but I didn't really find exactly what I want. I literally need it to send two commands.

Here's what I have tried (not the full code):

int main() {
  int iR;
  std::string input;
  std::cout << "Telnet ip: ";
  std::getline(std::cin, input);
  std::cout << std::endl;

  u_long ip = 0;
  u_short port = DEFAULT_PORT;
  u_long * ptr = &ip

  const char * cptr = input.c_str();
  inet_pton(AF_INET, cptr, ptr);

  std::cout << "Telnet port: ";
  std::getline(std::cin, input);
  std::cout << std::endl;
  iR = std::stoi(input);
  if((iR > SHRT_MAX) || (iR < 0)) {
    std::cout << "Wrong port number, using default." << std::endl;
  }
  else {
    port = iR;
  }

  WSADATA wsaData;
  iR = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (iR != 0) { return 1; }
  SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (server == INVALID_SOCKET) { WSACleanup(); return 1; }

  sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = ip;
  addr.sin_port = htons(port);

  std::string user;
  std::string pass;
  std::cout << "Username: ";
  std::getline(std::cin, user);
  std::cout << std::endl; << "Password: ";
  std::getline(std::cin, pass);
  std::cout << std::endl;

  std::cout << "Connecting..." << std::endl;
  if ((connect(server, (SOCKADDR *)&addr, sizeof(addr))) == SOCKET_ERROR) {
    std::cout << "Couldn't connect. << std::endl;
    WSAcleanup();
    Sleep(2000);
    return 0;
  }

  int bRecv = 0;
  char buff[2048];

  bRecv = recv(server, buff, sizeof(buff), 0);
  if ((bRecv == SOCKET_ERROR) || (bRecv == 0)) {
    std::cout << "Disconnected from the server." << std::endl;
    WSACleanup();
    return 0;
  }

  buff[bRecv] = 0;
  // When it connects successfully, a message appears on the screen from server
  std::cout << buff << std::endl;

  memset(buff, 0, sizeof(buff));
  std::string command = "login ";
  command.append(user);
  command.append(" ");
  command.append(pass);

  cptr = login.c_str();
  strcpy_s(buff, cptr);

  iR = send(server, buff, (u_int)strlen(buff), 0);
  if (iR == SOCKET_ERROR) { std::cout << "Couldn't send data." << std::endl; WSACleanup(); return 0;
  while (true) {
    bRecv = recv(server, buff, sizeof(buff), 0);
    if ((bRecv == SOCKET_ERROR) || (bRecv === 0)) {
      std::cout << "Disconnected from the server." << std::endl;
      break;
    }
    buff[bRecv] = 0;
    std::cout << buff << std::endl;
  }
  WSACleanup();
  return 0;
}

I mean I hope I'm not doing this the wrong way. I'm pretty much a begginer in C++.


Solution

  • You are not sending a line break after your command.

    std::string command = "login ";
    command.append(user);
    command.append(" ");
    command.append(pass);
    command.append("\r\n"); // <-- add this
    

    You also do not need to use buff to hold the command, you can send command directly:

    iR = send(server, command.c_str(), (u_int) command.length(), 0);