LIBSSH2 C с двойным стеком IPv4 и IPv6

#c #ipv6 #libssh2

Вопрос:

Я работаю над проектом на C , которому необходимо установить соединение по SSH с удаленным сервером, выполнить некоторые команды и передать файлы через SFTP. Однако мне нужно, чтобы это приложение работало в режиме двойного стека (например, с IPv6 и IPv4).

В приведенном ниже фрагменте моя программа изначально получает имя хоста, адрес IPv6 или IPv4. На входе IPv4 соединение выполнено успешно. Однако у меня возникают странные проблемы в режиме IPv6, когда я замечаю, что соединение установлено через сокет, и сеанс SSH не запускается.

В настоящее время я считаю, что это может быть что-то связанное с методом inet_ntop (). Пожалуйста, обратите внимание, что переменная remoteHost имеет тип char*, а удаленный порт-тип uint16_t.

 // Initialize some important variables uint32_t hostaddr = 0, hostaddr6 = 0; struct sockaddr_in sin = {}; struct sockaddr_in6 sinV6 = {}; int rc = 0, sock = 0, i = 0, auth_pw = 0;  // Here we will initialize our base class with username and password this-gt;username = usrName; this-gt;password = usrPassword;  // Firstly, we need to translate the hostname into an IPv4 or IPv6 address struct addrinfo hints={}, *sAdrInfo = {}; char addrstr[100]={}; void *ptr= nullptr; char addrParsed[50]={};  memset (amp;hints, 0, sizeof (hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags |= AI_CANONNAME;  // Now we need to get some address info from the one supplied that remoteHost parameter int errcode = getaddrinfo (remoteHost, nullptr, amp;hints, amp;sAdrInfo); if (errcode != 0) {  SERVER_ERROR("[SSH] Error while getaddrinfo at SSHConnect() code %d", errno);  return -4; }  inet_ntop(sAdrInfo-gt;ai_family, sAdrInfo-gt;ai_addr-gt;sa_data, addrstr, 100);  // Here we need to determine if we are using IPv6 or IPv4 switch (sAdrInfo-gt;ai_family) {  case AF_INET6:  ptr = amp;((struct sockaddr_in6 *) sAdrInfo-gt;ai_addr)-gt;sin6_addr;  break;  case AF_INET:  ptr = amp;((struct sockaddr_in *) sAdrInfo-gt;ai_addr)-gt;sin_addr;  break; } inet_ntop(sAdrInfo-gt;ai_family, ptr, addrstr, 100); sprintf(addrParsed, "%s", addrstr);  //This part is responsible for creating the socket and establishing the connection  // Now if we have an IPv4 based host if (sAdrInfo-gt;ai_family == AF_INET) {  this-gt;hostaddr = inet_addr(addrParsed);  sock = socket(AF_INET, SOCK_STREAM, 0);  sin.sin_family = AF_INET;  // Now we need to set these (address and port to our sockaddr_in variable sin)  sin.sin_port = htons(remotePort);  memcpy(amp;sin.sin_addr, amp;hostaddr, sizeof(hostaddr)); } // Now if we have an IPv6 based host else if (sAdrInfo-gt;ai_family == AF_INET6) {  this-gt;hostaddr6 = inet_addr(addrParsed);  sock = socket(AF_INET6, SOCK_STREAM, 0);  sin.sin_family = AF_INET6;  // Now we need to set these (address and port to our sockaddr_in variable sin)  sinV6.sin6_port = htons(remotePort);  memcpy(amp;sinV6.sin6_addr.s6_addr32, amp;hostaddr6, sizeof(this-gt;hostaddr6)); }  // Now we need to connect to our socket :D if (sAdrInfo-gt;ai_family == AF_INET) {  int resCon = connect(sock, (struct sockaddr*)(amp;sin), sizeof(struct sockaddr_in));   if (resCon != 0){  SERVER_ERROR("[SSH] failed to connect with error code: %d!n", errno);  return -1;  } } else if (sAdrInfo-gt;ai_family == AF_INET6) {  int resCon = connect(sock, (struct sockaddr*)(amp;sinV6), sizeof(struct sockaddr_in6));   if (resCon != 0){  SERVER_ERROR("[SSH] failed to connect with error code: %d!n", errno);  return -1;  } }  // Free our result variables freeaddrinfo(sAdrInfo);  // Create a session instance session = libssh2_session_init(); if(!session) {  return -2; }  /* Now to start the session. Here will trade welcome banners, exchange keys and setup crypto, compression,  * and MAC layers */ rc = libssh2_session_handshake(session, sock);  if(rc) {  SERVER_ERROR("Failure establishing SSH session: %dn", rc);  return -3; }  

Что не так с реализацией, которая генерирует сообщение «Сбой при установлении сеанса SSH» со стеком IPv6?

С уважением,

Комментарии:

1. Что такое inet_ntop() возвращение? Согласно справочной странице, он возвращается NULL , если возникает системная ошибка, и устанавливает errno значение, указывающее, в чем заключалась ошибка. Похоже, это было бы полезной информацией для вас.

2. Он возвращает большое количество. Я повторно реализовал с помощью inet_pton и внес много изменений. Кажется, это решено. Я скоро опубликую здесь решение.