C libpcap API extracting DNS query

只谈情不闲聊 提交于 2021-02-10 06:42:09

问题


I am trying to extract a DNS query from an captured DNS packet with libpcap api, however there must be a problem with my structures, after the last cast (using struct question) the char* name pointer is pointing at correct adress, the start of the query name, however it contains only

42 45 20 00

but it should

20 45 48 45 50 45 50 45 48 45 4d 45 46 43 4f 45 44 45 50 45 4e 43 41 43 41 43
41 43 41 43 41 41 41 00 00 20 00 01

The code is here

struct dnshdr{
    uint16_t id;
    uint16_t flags;
    uint16_t ques;
    uint16_t anRR;
    uint16_t auRR;
    uint16_t addRR;
};

struct question{
    char * name;
    uint16_t type;
    uint16_t cls;
};



void packetProc(u_char *args, const struct pcap_pkthdr *header,const u_char *packet){
   struct iphdr *IP_header;
   struct udphdr *UDP_header;
   struct dnshdr *DNS_header;
   struct question *ques;

   IP_header =  (struct iphdr*)    (packet + sizeof(struct ethhdr));
   UDP_header = (struct udphdr*)   (packet + sizeof(struct iphdr)  + sizeof(struct ethhdr));
   DNS_header = (struct dnshdr*)   (packet + sizeof(struct iphdr)  + sizeof(struct ethhdr)  +  sizeof(struct udphdr) );
   ques =       (struct question*) (packet + sizeof(struct ethhdr) + sizeof(struct iphdr)   +  sizeof(struct udphdr) + sizeof(struct dnshdr)-1 ); //fatal       
}

I am honestly puzzled what to do here


回答1:


struct question{
    char * name;
    uint16_t type;
    uint16_t cls;
};

the way you use this struct is invalid. char * is a pointer to memory location containing characters. DNS query does not have a pointer value to your computer memory location containing characters, the query contains those characters. However the length of the DNS query name (ie. char name[how much should be put here]) is calculated from the length of the udp message. You can:

struct question_after_name_s { 
        uint16_t type;
        uint16_t cls;
};

...
const size_t namepos = 2*6; // name position in bytes form the beginning of the DNS query, this should be equal to 'sizeof(struct ethhdr) + sizeof(struct iphdr)   +  sizeof(struct udphdr) + sizeof(struct dnshdr)-1 ' from your code
char *name = (char*)&packet[namepos]; // the pointer name should point to the location in packet after namepos bytes
const size_t packetlen = header->len; // I guess this is received DNS query length obtained from libcap
const size_t querytypeandclasslen = 2*2; // length of the query type and query class, should be equal to sizeof(struct question_after_name_s)
const size_t namelen = packetlen - namepos - querytypeandclasslen;
printf("DNS query name = '%.*s'\n", namelen, name);
struct question_after_name_s *ptr = (void*)&packet[namepos + namelen];
//or
struct question_after_name_s *ptr = (void*)&packet[];

Of course such casting is correct only, if your compiler does not insert any padding between members of the structure (hope you use gcc compiler with attribute((packed)) on those structs) and you call ntohl family functions or be16toh family functions to convert between the packet endianess and your host endianess.



来源:https://stackoverflow.com/questions/51376598/c-libpcap-api-extracting-dns-query

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!