代理DNS未收到响应

时间:2012-11-17 19:01:05

标签: c sockets dns udp

我正在创建代理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;
    }
  }
}

1 个答案:

答案 0 :(得分: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) ,才能将端口号转换为network byte order