2012-11-17 61 views
1

我正在創建代理DNS,我從dig收到查詢,發送給服務器,但無法從DNS服務器獲得答案。我知道我的代碼看起來不太好,但我在這工作了幾個小時,仍然無法解決問題。我的程序在第二次recvfrom之前就卡住了。有人能幫我嗎? (順便說一句我的這個操作系統是FreeBSD和我與8.8.8.8 DNS服務器測試這個)代理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

至少有兩個問題在這裏:

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
+0

就是這樣,並再次請幫助。現在看起來它正在工作。整個循環被執行並挖掘得到響應,但它不包含ANSWER部分。這個問題在哪裏? –

+0

沒關係,我在serverbuf的第二個recvform中和上一個sendto中更改了buf,它正在工作。感謝幫助 –