如何在Windows上使用libssh在C中执行端口转发

时间:2019-12-12 17:17:55

标签: c multithreading libssh

下面是我在本文的帮助下写的一段代码:C: can I forward port for external application with libssh?

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; /* initialize the mutex  */

struct arg_struct 
{
  int sockfd;           /* client socket */
  ssh_session session;  /* ssh session */
  char *rhost;          /* remote where we perform forwarding */
  int rport;            /* ssh port */
  int lport;            /* local port to listen on */
};

/* forward_handler: handle the port forwarding for every thread */
void *forward_handler(void *arg)
{
  char data[4060];
  int rc, recvl, nwritten, nread;
  ssh_channel forwarding_channel;
  struct arg_struct *args = (struct arg_struct*)arg;

  pthread_mutex_lock(&lock); /* lock mutex until task complete */

  /* requests on the fd can return immediately with a failure status if no input, vs blocking */
  if ((fcntl(args->sockfd, F_SETFL, O_NONBLOCK)) != 0)
    goto exit;

  /* get pointer to a newly allocated channel, NULL on error */
  if ((forwarding_channel = ssh_channel_new(args->session)) == NULL) {
    perror("Error");
    goto exit;
  }

  /* open a TCP/IP forwarding channel, SSH_OK if successfull */
  rc = ssh_channel_open_forward(forwarding_channel,
                                args->rhost, args->rport,
                                "127.0.0.1", args->lport);
  if (rc != SSH_OK) {
    perror("Error");
    goto exit;
  }

  printf("Connected! Tunnel open (127.0.0.1:%d) -> (ssh://%s) -> (\"%s:%d\")\n",
    args->lport, args->rhost, args->rhost, args->rport
  );

  /* while we have an open channel and channel has NOT sent an EOF response */
  while(ssh_channel_is_open(forwarding_channel) && !ssh_channel_is_eof(forwarding_channel))
  {
    if ((recvl = recv(args->sockfd, data, sizeof(data), MSG_DONTWAIT)) < 0)                       /* recieve data & enable nonblocking */
      if ((nread = ssh_channel_read_nonblocking(forwarding_channel, data, sizeof(data), 0)) > 0)  /* do a nonblocking read on the channel */
        if ((write(args->sockfd, data, nread)) < 0)                                               /* write to socket */
        {
          perror("Error");
          goto exit;
        }
    else if (!recvl) {
      printf("Local client disconnected, exiting\n");
      goto exit;
    }
    nwritten = ssh_channel_write(forwarding_channel, data, recvl); /* send to the remote host */
    if (recvl != nwritten) {
      perror("Error");
      goto exit;
    }
  }
exit:
  ssh_channel_free(forwarding_channel); /* free the forwarding channel */
  pthread_mutex_unlock(&lock);          /* unlock mutex */
  close(args->sockfd);                  /* close socket file descriptor */
  pthread_exit(NULL);                   /* exit thread */
}

此代码尚未经过优化和严格测试,并且tbh相当快地编写了该代码,需要对其进行检查,但是目前它作为我的POC在Linux上可以工作。当我尝试在Windows上执行相同操作时,主要在以下几行中遇到问题:

  if ((fcntl(args->sockfd, F_SETFL, O_NONBLOCK)) != 0)
    goto exit;
---snip---
    if ((recvl = recv(args->sockfd, data, sizeof(data), MSG_DONTWAIT)) < 0)                       /* recieve data & enable nonblocking */
      if ((nread = ssh_channel_read_nonblocking(forwarding_channel, data, sizeof(data), 0)) > 0)  /* do a nonblocking read on the channel */
        if ((write(args->sockfd, data, nread)) < 0)                                               

以下是我要解决的尝试:

/* forward_handler: handle the port forwarding for every thread */
void *forward_handler(void *arg)
{
  char data[4096];
  unsigned long int iMode = 1;
  int rc, recvl, nwritten, nread;
  ssh_channel forwarding_channel;
  struct arg_struct *args = (struct arg_struct*)arg;

  pthread_mutex_lock(&lock); /* lock mutex until task complete */

  /* requests on the fd can return immediately with a failure status if no input, vs blocking */
  if ((ioctlsocket(args->sockfd, FIONBIO, &iMode)) != NO_ERROR)
    goto exit;

  /* get pointer to a newly allocated channel, NULL on error */
  if ((forwarding_channel = ssh_channel_new(args->session)) == NULL) {
    fprintf(stderr, "forward_handler: Failed to create new channel with error: %d\n", forwarding_channel);
    exit(0);
  }

  /* open a TCP/IP forwarding channel, SSH_OK if successfull */
  rc = ssh_channel_open_forward(forwarding_channel,
                                args->rhost, args->rport,
                                "127.0.0.1", args->lport);
  if (rc != SSH_OK) {
    fprintf(stderr, "forward_handler: Failed to open forwarding channel with error: %d\n", rc);
    goto exit_and_free;
  }

  printf("Connected! Tunnel open (127.0.0.1:%d) -> (ssh://%s) -> (\"%s:%d\")\n",
    args->lport, args->rhost, args->rhost, args->rport
  );

  /* while we have an open channel and channel has NOT sent an EOF response */
  while(ssh_channel_is_open(forwarding_channel) && !ssh_channel_is_eof(forwarding_channel))
  {
    if ((recvl = recv(args->sockfd, data, sizeof(data), 0)) < 0) {
      if ((nread = ssh_channel_read_nonblocking(forwarding_channel, data, sizeof(data), 0)) > 0)  /* do a nonblocking read on the channel */
        if ((WriteFile((HANDLE)args->sockfd, data, nread, NULL, NULL)) < 0)                       /* write to socket */
        {
          fprintf(stderr, "forward_handler: Error writing to file descriptor");
          goto exit_and_free;
        }
    }
    else if (!recvl) {
      printf("Local client disconnected, exiting\n");
      goto exit_and_free;
    }
    nwritten = ssh_channel_write(forwarding_channel, data, recvl); /* send to the remote host */
    if (recvl != nwritten) {
      fprintf(stderr, "forward_handler: Error writing to SSH channel\n");
      goto exit_and_free;
    }
  }
exit_and_free:
  ssh_channel_free(forwarding_channel); /* free the forwarding channel */
exit:
  pthread_mutex_unlock(&lock);          /* unlock mutex */
  close(args->sockfd);                  /* close socket file descriptor */
  pthread_exit(NULL);                   /* exit thread */
}

因为我被卡住了,所以打败了我,因为糟糕的代码:)

0 个答案:

没有答案