2011-03-12 99 views
0

我正在嘗試編寫一個程序,該程序可以在不使用c中的任何DNS功能的情況下從DNS答覆中刪除一個IP地址。由於某些原因,此代碼可用,但僅適用於谷歌,臉書和imgur.com。如同輸入「www.facebook.com」一樣,它提供了正確的IP地址,與其他兩個站點一樣,但輸入的任何其他站點都給出了錯誤的IP地址。有誰知道我做錯了什麼?從DNS響應中獲取IP

#include <stdio.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <stdlib.h> 

#define PORT 53 
#define SITEMAXLEN 40 
#define QUERYMAXLEN SITEMAXLEN + 16 
#define DNSRESULTMAXLEN 100 
#define IPARRAYLEN 20 

typedef unsigned char char_type; 

void enter_record(char_type* query, char_type* site, int* let_set); 
void print_query(char_type* query, int len); 
void send_query(char_type* query, char_type* result, int len, int* answer_set); 
char_type* parse_result(char_type* result, int query_len, char_type* ip); 
void print_ip(int* ip); 

int sock; 
struct sockaddr_in server_addr; 
struct sockaddr_in from_addr; 
int main(int argc, char_type** argv) { 
    char_type* site; 
    char_type* query; 
    char_type* dns_result; 
    char_type* ip; 

    int query_len; 
    int answer_len; 

    site = (char_type*)malloc(SITEMAXLEN * sizeof(char_type)); 
    query = (char_type*)malloc((QUERYMAXLEN) * sizeof(char_type)); 
    dns_result = (char_type*)malloc(DNSRESULTMAXLEN * sizeof(char_type)); 
    ip = (char_type*)malloc(IPARRAYLEN * sizeof(char_type)); 

    if((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 
     fprintf(stderr, "error creating socket to the name server\n"); 
     return 1; 
    } 

    memset(&server_addr, 0, sizeof(server_addr)); 
    server_addr.sin_family = AF_INET; 
    server_addr.sin_addr.s_addr = inet_addr("208.67.220.220"); 
    server_addr.sin_port = htons(PORT); 

    printf("enter in website name\n"); 
    scanf("%s", site); 

    enter_record(query, site, &query_len); 
    print_query(query, query_len); 
    send_query(query, dns_result, query_len, &answer_len); 
    printf("\n\nresult is\n"); 
    print_query(dns_result, answer_len); 
    parse_result(dns_result, query_len, ip); 
    printf("\n\nip address is: %s", ip); 

    return 0; 
} 

void enter_record(char_type* query, char_type* site, int* len_set) { 
    char_type* loc; 
    char_type* len; 
    char_type* tld; 
    int query_end; 

    loc = strchr(site, '.'); //. after www 
    len = strchr(loc + 1, '.'); //. after the hostname 
    *loc = (char_type)(len - loc - 1); 
    *len = (char_type)0x0003; 

    query[0] = 'B'; 
    query[1] = 'L'; 
    query[2] = (char_type)0x0001; 
    query[3] = (char_type)0x0000; 
    query[4] = (char_type)0x0000; 
    query[5] = (char_type)0x0001; 
    query[6] = (char_type)0x0000; 
    query[7] = (char_type)0x0000; 
    query[8] = (char_type)0x0000; 
    query[9] = (char_type)0x0000; 
    query[10] = (char_type)0x0000; 
    query[11] = (char_type)0x0000; 
    query[12] = (char_type)0x0003; 
    strncat(query + 13, site, strlen(site)); 

    query_end = 13 + strlen(site); 
    query[query_end] = 0x0000; 
    query[query_end + 1] = 0x0000; 
    query[query_end + 2] = 0x0001; 
    query[query_end + 3] = 0x0000; 
    query[query_end + 4] = 0x0001; 

    *len_set = query_end + 5; 
} 

void print_query(char_type* query, int len) { 
    int i; 

    printf("in hex\n"); 
    for(i = 0; i < len; i++) { 
     printf("%02hhX ", query[i]); 

     if(i % 16 == 0 && i != 0) { 
      printf("\n"); 
     } 
    } 
    printf("\nin ascii\n"); 

    for(i = 0; i < len; i++) { 
     printf("%c ", query[i] < (char_type)0x21 ? '.' : query[i]); 

     if(i % 16 == 0 && i != 0) { 
      printf("\n"); 
     } 
    } 
    printf("\n"); 
} 

void send_query(char_type* query, char_type* result, int len, int* set_len) { 
    int from_size; 
    int response_len; 

    if(sendto(sock, query, len, 0, 
    (struct sockaddr*)&server_addr, sizeof(server_addr)) != len) { 
     //message couldn't be sent 
     fprintf(stderr, "couldn't send the query\n"); 
     return; 
    } 

    from_size = sizeof(from_addr); 
    while((response_len = recvfrom(sock, result, DNSRESULTMAXLEN, 0, 
    (struct sockaddr*)&from_addr, &from_size)) < 0) { 
    } 

    //null terminate the buffer 
    //printf("%d\n", response_len); 
    //result[response_len] = '\0'; 

    *set_len = response_len; 
} 

char_type* parse_result(char_type* result, int query_len, char_type* ip) { 
    /*int offset = -1; 

    //offset = query_len + 32; 
    int count = 0; 
    while(count < 3) { 
     offset++; 
     if(result[offset] == 0x00C0) { 
      count++; 
     } 
    } 

    offset += 32;*/ 

    int offset = -1; 
    int found = 0; 
    while(found == 0) { 
     offset++; 
     if(result[offset] == 0x00C0) { 
      if(result[offset + 3] == 0x0001 && result[offset + 2] == 0x0000) { 
       offset = offset + result[offset + 1]; 
       found = 1; 
      } 
     } 
    } 

    sprintf(ip, "%d.%d.%d.%d\n", 
    result[offset], result[offset + 1], 
    result[offset + 2], result[offset + 3]); 

    return ip; 
} 
+3

請詳細描述什麼是不工作 – 2011-03-12 03:26:37

+0

編輯。除了提到的三個站點之外,IP地址是錯誤的 – ThatQuestionGuy 2011-03-12 03:29:10

回答

0

parse_result()代替跳躍result[offset + 1]字節,跳12個字節。

  if(result[offset + 3] == 0x0001 && result[offset + 2] == 0x0000) { 
       /* ******** 
       offset = offset + result[offset + 1]; 
       ******** */ 
       offset = offset + 12; 
       found = 1; 
      } 

結果[offset + 1]上的值是從消息的開頭到名稱而不是ip地址的偏移量。在雅虎的情況下,抵消最終指向"any-fp.wa1.b.yahoo.com"


它的工作爲Facebook(及其他),因爲偏移的答案名稱是12偏移量是12時,在問題的名稱是相同的答案名稱。


更新

並非所有的DNS響應啓動一個指針(0xC0 0x??)每個答案部分。他們可能會有一個標籤,而你的程序會失敗。即使指針的第一個字節不需要爲0xC0:要求設置前2位。