1

我正在创建代理 dns,我收到了来自 dig 的查询,将其发送到服务器,但无法从 dns 服务器获得答案。我知道我的代码看起来不太好,但我已经为此工作了好几个小时,但仍然无法找出问题所在。我的程序在第二次 recvfrom 之前卡住了。有人能帮我吗?(顺便说一句,我的操作系统是 FreeBSD,我正在使用 8.8.8.8 dns 服务器进行测试)

这是我的代码:

int main(int argc, char *argv[] )
{

  char buf[BUFSIZE];
  char serverbuf[BUFSIZE];
  int UDPSocket, clientSocket;
  int lenght;
  int addr_len;
  struct addrinfo *clientInfo;
  struct addrinfo hintsClient;
  struct sockaddr_in serverSocket, clientAddr, serverAddr;
  int serverAddrLen = sizeof(serverAddr);
  fd_set set, tcpset;
  struct timeval tv; // struktura pro timeout
  bool end = false;
  int m;

  TprogParam param = processParams(argc, argv);
  if(param.error)
  {
    printError(EPARAMS);
    return ERROR;
  }
  if(param.help)
  {
    printHelp();
    return EXIT_SUCCESS;
  }

  memset(&hintsClient, 0, sizeof(struct addrinfo));
  hintsClient.ai_family = AF_INET;
  hintsClient.ai_socktype = SOCK_DGRAM;
  hintsClient.ai_flags = 0;
  hintsClient.ai_protocol = IPPROTO_UDP;

  int status;


  if(param.ipadress[0] == '\0')
  {
    if((status = getaddrinfo(INADDR_ANY, NULL, &hintsClient, &clientInfo)) != 0)
    {
      printf("Spatna adresa pro naslouchani");
      printError(1);
      return ERROR;
    }
  }
  else
  {
    if((status = getaddrinfo(param.ipadress, "13066", &hintsClient, &clientInfo)) != 0)
    {
      printf("Spatna adresa pro naslouchani");
      printError(1);
      return ERROR;
    }
  }


  memset(&serverAddr, 0, sizeof(serverAddr));
  serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(param.dnsserver);;
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddr.sin_port = 53;

  // vytvorime socket
  if((UDPSocket = socket(clientInfo->ai_family, clientInfo->ai_socktype, clientInfo->ai_protocol)) == -1)
  {
    printf("Nelze vytvorit udp socket");
    printError(1);
    return ERROR;
  }

  if((clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  {
    printf("Nelze vytvorit tcp socket");
    printError(1);
    return ERROR;
  }


  // Nastavime socket do neblokovaciho rezimu


  if(bind(UDPSocket, clientInfo->ai_addr, clientInfo->ai_addrlen) == -1)
  {
    if (errno != EINPROGRESS)
    {
      printf("Nelze navazat spojeni pro naslouchani: %d", errno);
      return ERROR;
    }
  }
  printf("Poslal jsem zadost o spojeni. Zatimco se spojeni navazuje mohu delat jine veci.\n");

  FD_ZERO(&set);
  FD_SET(UDPSocket, &set);
  tv.tv_sec = 15;
  tv.tv_usec = 0;

  addr_len = sizeof(struct sockaddr);
  while(1)
  {
      printf("Prijimam pozadavek k vyrizeni.\n");
      if ((lenght = recvfrom(UDPSocket, buf, BUFSIZE - 1, 0, (struct sockaddr *)&clientAddr, &addr_len)) == -1)//recv(UDPSocket, buf, BUFSIZE - 1, 0)) == -1)
      {
        printf("Nejaka chyba pri prijimani dat");
        return ERROR;
      }
      buf[lenght] = '\0';
      printf("Prijata nasledujici data od klienta na predklad dns: %s o delce %d \n", buf, lenght);

      if((m = sendto(clientSocket, buf, lenght, 0, (struct sockaddr *)&serverAddr, serverAddrLen)) == -1)
      {
        printf("Problem s odeslanim dat: %d %s", errno, strerror(errno));
        return ERROR;
      }

      if((m = recvfrom(clientSocket, buf, BUFSIZE - 1, 0, (struct sockaddr *)&serverAddr,&serverAddrLen)) == -1)
      {
        printf("nejaka chyba");
        return ERROR;
      }

    if((lenght = sendto(UDPSocket, buf, lenght, 0,(struct sockaddr *)&clientAddr, lenght)) == -1)
    {
      printf("Problem s odeslanim dat: errno %d", errno);
      return ERROR;
    }
  }
}

编辑:一些修复后的新代码:

#include "dns_stat.h"

TprogParam processParams(int argc, char *argv[]) {

TprogParam parInfo =
{
.error = false,
.help = false,
.ipadress[0] = '\0',
.port = 0,
.dnsserver[0] = '\0',
.type = false,
.source = false,
.destination = false,
};

if(argc == 1)
{
  parInfo.help = true;
}
else
{
  int c;
  const char *short_options = ":l:p:s:";

  const struct option long_options[] = {
    { "type", 0, NULL, 't' },
    { "source", 0, NULL, 'z' },
    { "destination", 0, NULL, 'd' },
    { NULL, 0, NULL, 0 }
  };
  while((c = getopt_long_only(argc, argv, short_options, long_options, NULL)) != -1) {
    switch (c) {
      case 'l':
        strcpy(parInfo.ipadress,optarg);
        break;
      case 'p':
        parInfo.port = atoi(optarg);
        break;
      case 's':
        strcpy(parInfo.dnsserver,optarg);//optarg);
        //parInfo.dnsserver = strdup(optarg);
        break;
      case 't':
        parInfo.type = true;
        break;
      case 'z':
        parInfo.source = true;
        break;
      case 'd':
        parInfo.destination = true;
        break;
      case '?':
        parInfo.error = true;
        break;
      default:
        printf("default");
        parInfo.error = true;
        abort();
    }
  }
}

return parInfo;
}

void printHelp()
{
  printf("Napoveda\n");
}
void printError(int ecode)
{
  if(ecode<EOK||ecode>EUNKNOWN){
    ecode = EUNKNOWN;
  }
  fprintf(stderr, "%s", ECODEMSG[ecode]);
}
int main(int argc, char *argv[] )
{

  char buf[BUFSIZE];
  char serverbuf[BUFSIZE];
  int UDPSocket, clientSocket;
  int lenght;
  int addr_len;
  struct addrinfo *clientInfo;
  struct addrinfo hintsClient;
  struct sockaddr_in serverSocket, clientAddr, serverAddr;
  int serverAddrLen = sizeof(serverAddr);
  fd_set set, tcpset;
  struct timeval tv; // struktura pro timeout
  bool end = false;
  bool end2 = false;
  int m;

  TprogParam param = processParams(argc, argv);
  if(param.error)
  {
    printError(EPARAMS);
    return ERROR;
  }
  if(param.help)
  {
    printHelp();
    return EXIT_SUCCESS;
  }

  //printf("type: %d, source: %d, destination: %d\n", param.type, param.source, param.destination);
  memset(&hintsClient, 0, sizeof(struct addrinfo));
  hintsClient.ai_family = AF_INET;
  hintsClient.ai_socktype = SOCK_DGRAM;
  hintsClient.ai_flags = 0;
  hintsClient.ai_protocol = IPPROTO_UDP;

  int status;


  if(param.ipadress[0] == '\0')
  {
    if((status = getaddrinfo(INADDR_ANY, NULL, &hintsClient, &clientInfo)) != 0)
    {
      printf("Spatna adresa pro naslouchani");
      printError(1);
      return ERROR;
    }
  }
  else
  {
    if((status = getaddrinfo(param.ipadress, "13066", &hintsClient, &clientInfo)) != 0)
    {
      printf("Spatna adresa pro naslouchani");
      printError(1);
      return ERROR;
    }
  }


  memset(&serverAddr, 0, sizeof(serverAddr));
;
  serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(param.dnsserver);;
    serverAddr.sin_port = htons(53);

  // vytvorime socket
  if((UDPSocket = socket(clientInfo->ai_family, clientInfo->ai_socktype, clientInfo->ai_protocol)) == -1)
  {
    printf("Nelze vytvorit udp socket");
    printError(1);
    return ERROR;
  }

  if((clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  {
    printf("Nelze vytvorit tcp socket");
    printError(1);
    return ERROR;
  }


  // Nastavime socket do neblokovaciho rezimu


  if(bind(UDPSocket, clientInfo->ai_addr, clientInfo->ai_addrlen) == -1)
  {
    if (errno != EINPROGRESS)
    {
      printf("Nelze navazat spojeni pro naslouchani: %d", errno);
      return ERROR;
    }
  }
  printf("Poslal jsem zadost o spojeni. Zatimco se spojeni navazuje mohu delat jine veci.\n");

  FD_ZERO(&set);
  FD_SET(UDPSocket, &set);
  tv.tv_sec = 15;
  tv.tv_usec = 0;

  addr_len = sizeof(struct sockaddr);
  while(1)
  {
      printf("Prijimam pozadavek k vyrizeni.\n");
      if ((lenght = recvfrom(UDPSocket, buf, BUFSIZE - 1, 0, (struct sockaddr *)&clientAddr, &addr_len)) == -1)//recv(UDPSocket, buf, BUFSIZE - 1, 0)) == -1)
      {
        printf("Nejaka chyba pri prijimani dat");
        return ERROR;
      }
      buf[lenght] = '\0';
      printf("Prijata nasledujici data od klienta na predklad dns: %s o delce %d \n", buf, lenght);

      if((m = sendto(clientSocket, buf, lenght, 0, (struct sockaddr *)&serverAddr, serverAddrLen)) == -1)
      {
        printf("Problem s odeslanim dat: %d %s", errno, strerror(errno));
        return ERROR;
      }
      printf("tady");
      fflush(stdout);
      if((m = recvfrom(clientSocket, buf, BUFSIZE - 1, 0, (struct sockaddr *)&serverAddr,&serverAddrLen)) == -1)
      {
        printf("nejaka chyba");
        return ERROR;
      }

      printf("Prijata nasledujici data od dns serveru: %s o delce %d \n", buf, lenght);

    if((lenght = sendto(UDPSocket, buf, lenght, 0,(struct sockaddr *)&clientAddr, addr_len)) == -1)
    {
      printf("Problem s odeslanim dat: errno %d %s", errno, strerror(errno));
      return ERROR;
    }
  }
}
4

1 回答 1

1

这里至少有两个问题:

serverAddr.sin_addr.s_addr = inet_addr(param.dnsserver);; /* line 1 */
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* line 2 */
serverAddr.sin_port = 53; /* line 3 */
  • 第 2 行覆盖您刚刚在第 1 行翻译的服务器地址。只需删除第 2 行。
  • 第 3 行需要更改为htons(53)将端口号转换为网络字节顺序
于 2012-11-17T19:07:29.937 回答