Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "../includes/dns.h"
- u_char* ReadName(unsigned char* reader,unsigned char* buffer,int* count)
- {
- unsigned char *name;
- unsigned int p=0,jumped=0,offset;
- int i , j;
- *count = 1;
- name = (unsigned char*)malloc(256);
- name[0]='\0';
- //read the names in 3www6google3com format
- while(*reader!=0)
- {
- if(*reader>=192)
- {
- offset = (*reader)*256 + *(reader+1) - 49152; //49152 = 11000000 00000000 ;)
- reader = buffer + offset - 1;
- jumped = 1; //we have jumped to another location so counting wont go up!
- }
- else
- {
- name[p++]=*reader;
- }
- reader = reader+1;
- if(jumped==0)
- {
- *count = *count + 1; //if we havent jumped to another location then we can count up
- }
- }
- name[p]='\0'; //string complete
- if(jumped==1)
- {
- *count = *count + 1; //number of steps we actually moved forward in the packet
- }
- //now convert 3www6google3com0 to www.google.com
- for(i=0;i<(int)strlen((const char*)name);i++)
- {
- p=name[i];
- for(j=0;j<(int)p;j++)
- {
- name[i]=name[i+1];
- i=i+1;
- }
- name[i]='.';
- }
- name[i-1]='\0'; //remove the last dot
- return name;
- }
- void parse_dns_header(struct DNS_HEADER *dns) {
- printf("\nDNS HEADER:\n");
- printf("id: %d\n \
- rd: %d\n \
- tc: %d\n \
- aa: %d\n \
- opcode: %d\n \
- qr: %d\n \
- rcode: %d\n \
- cd: %d\n \
- ad: %d\n \
- z: %d\n \
- ra: %d\n \
- q_count: %d\n \
- ans_count: %d\n \
- auth_count: %d\n \
- add_count: %d\n", ntohs(dns->id), ntohs(dns->rd), ntohs(dns->tc),
- ntohs(dns->aa), ntohs(dns->opcode), ntohs(dns->qr),
- ntohs(dns->rcode), ntohs(dns->cd), ntohs(dns->ad),
- ntohs(dns->z), ntohs(dns->ra), ntohs(dns->q_count),
- ntohs(dns->ans_count), ntohs(dns->auth_count),
- ntohs(dns->add_count));
- }
- char *parse_query(char *q) {
- //char *location = q;
- char *name = NULL;
- int l = 0;
- int i, j;
- name = (char*)calloc(512, sizeof(char));
- if (name == NULL) {
- exit(1);
- }
- while(*q != 0) {
- name[l] = *q;
- l++;
- q++;
- }
- q++;
- for(i = 0; i < l; i++) {
- int p = name[i];
- for(j = 0; j < (int)p; j++) {
- name[i] = name[i + 1];
- i++;
- }
- name[i] = '.';
- }
- name[i - 1] = '\0';
- struct QUESTION *qinfo = (struct QUESTION*)q;
- hexDump("Q", qinfo, sizeof(struct QUESTION));
- int type = ntohs(qinfo->qtype);
- int class = ntohs(qinfo->qclass);
- printf("Query name: %s\n", name);
- printf("Query type: %d\n", type);
- printf("Query class: %d\n\n", class);
- free(name);
- q += 4;
- return q;
- }
- char *parse_rr(struct RES_RECORD* rr) {
- char *name = NULL;
- char *data = NULL;
- char *location = (char*)rr;
- char *loc = location;
- int l = 0;
- int i, j;
- int data_len, rr_type;
- name = (char*)calloc(512, sizeof(char));
- if (name == NULL) {
- exit(1);
- }
- while(*location != 0) {
- name[l] = *location;
- l++;
- location++;
- }
- location++;
- for(i = 0; i < l; i++) {
- int p = name[i];
- for(j = 0; j < (int)p; j++) {
- name[i] = name[i + 1];
- i++;
- }
- name[i] = '.';
- }
- name[i - 1] = '\0';
- printf("Name of record: %s\n", name);
- free(name);
- struct R_DATA *rdata = (struct R_DATA*)location;
- printf("type: %d\n", ntohs(rdata->type));
- printf("_class: %d\n", ntohs(rdata->_class));
- printf("ttl: %d\n", ntohl(rdata->ttl));
- printf("rdata_len: %d\n", ntohs(rdata->data_len));
- data_len = ntohs(rdata->data_len);
- rr_type = ntohs(rdata->type);
- location += sizeof(struct R_DATA);
- //location -= 1;
- struct sockaddr_in ipv4;
- struct sockaddr_in6 ipv6;
- long *p;
- switch (rr_type) {
- case A:
- p = (long*)location;
- ipv4.sin_addr.s_addr = (*p);
- printf("has IPv4 address : %s", inet_ntoa(ipv4.sin_addr));
- break;
- case AAAA:
- /*p = (long*)data;
- ipv6.sin6_addr.s6_addr = (*p);
- printf("has IPv6 address : %s", inet_ntop(ipv6.sin6_addr));*/
- hexDump("ipv6", location, 16);
- break;
- case PTR:
- printf("PTR\n");
- break;
- case TXT:
- printf("TXT\n");
- break;
- case SRV:
- break;
- case ANY:
- break;
- case OTP:
- printf("It's an OTP rr!\n");
- break;
- default:
- break;
- }
- location += data_len;
- return location;
- }
- /*u_char* ReadName(char* reader, char* buffer, int* count) {
- unsigned char *name;
- unsigned int p = 0, jumped = 0;
- int i , j;
- *count = 1;
- name = (unsigned char*)malloc(256);
- name[0]='\0';
- //read the names in 3www6google3com format
- while(*reader!=0) {
- name[p++]=*reader;
- reader = reader+1;
- if(jumped == 0) {
- *count = *count + 1; //if we havent jumped to another location then we can count up
- }
- }
- name[p]='\0'; //string complete
- if(jumped==1) {
- *count = *count + 1; //number of steps we actually moved forward in the packet
- }
- //now convert 3www6google3com0 to www.google.com
- for(i = 0; i < (int)strlen((const char*)name); i++) {
- p=name[i];
- for(j = 0; j < (int)p; j++) {
- name[i] = name[i+1];
- i = i+1;
- }
- name[i] = '.';
- }
- name[i - 1] = '\0'; //remove the last dot
- return name;
- }*/
- void parse(char *buf, int len) {
- unsigned char buf[65536],*qname,*reader;
- int i , j , stop , s;
- struct sockaddr_in a;
- struct RES_RECORD answers[20],auth[20],addit[20]; //the replies from the DNS server
- struct sockaddr_in dest;
- struct DNS_HEADER *dns = NULL;
- struct QUESTION *qinfo = NULL;
- printf("Resolving %s" , host);
- stop=0;
- dns = (struct DNS_HEADER *)&buf;
- qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)];
- dns = (struct DNS_HEADER*) buf;
- //move ahead of the dns header and the query field
- reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)];
- printf("\nThe response contains : ");
- printf("\n %d Questions.",ntohs(dns->q_count));
- printf("\n %d Answers.",ntohs(dns->ans_count));
- printf("\n %d Authoritative Servers.",ntohs(dns->auth_count));
- printf("\n %d Additional records.\n\n",ntohs(dns->add_count));
- //Start reading answers
- for(i=0;i<ntohs(dns->ans_count);i++)
- {
- answers[i].name=ReadName(reader,buf,&stop);
- reader = reader + stop;
- answers[i].resource = (struct R_DATA*)(reader);
- reader = reader + sizeof(struct R_DATA);
- if(ntohs(answers[i].resource->type) == 1) //if its an ipv4 address
- {
- answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len));
- for(j=0 ; j<ntohs(answers[i].resource->data_len) ; j++)
- {
- answers[i].rdata[j]=reader[j];
- }
- answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0';
- reader = reader + ntohs(answers[i].resource->data_len);
- }
- else
- {
- answers[i].rdata = ReadName(reader,buf,&stop);
- reader = reader + stop;
- }
- }
- //read authorities
- for(i=0;i<ntohs(dns->auth_count);i++)
- {
- auth[i].name=ReadName(reader,buf,&stop);
- reader+=stop;
- auth[i].resource=(struct R_DATA*)(reader);
- reader+=sizeof(struct R_DATA);
- auth[i].rdata=ReadName(reader,buf,&stop);
- reader+=stop;
- }
- //read additional
- for(i=0;i<ntohs(dns->add_count);i++)
- {
- addit[i].name=ReadName(reader,buf,&stop);
- reader+=stop;
- addit[i].resource=(struct R_DATA*)(reader);
- reader+=sizeof(struct R_DATA);
- if(ntohs(addit[i].resource->type)==1)
- {
- addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len));
- for(j=0;j<ntohs(addit[i].resource->data_len);j++)
- addit[i].rdata[j]=reader[j];
- addit[i].rdata[ntohs(addit[i].resource->data_len)]='\0';
- reader+=ntohs(addit[i].resource->data_len);
- }
- else
- {
- addit[i].rdata=ReadName(reader,buf,&stop);
- reader+=stop;
- }
- }
- }
- void parse_dns(char *buf, int len) {
- struct DNS_HEADER *dns = NULL;
- int i;
- int questions, answers, authorities, additional;
- dns = (struct DNS_HEADER*) buf;
- questions = ntohs(dns->q_count);
- answers = ntohs(dns->ans_count);
- authorities = ntohs(dns->auth_count);
- additional = ntohs(dns->add_count);
- hexDump("Received", buf, len);
- printf("\n%d Questions.", questions);
- printf("\n%d Answers.", answers);
- printf("\n%d Authoritative Servers.", authorities);
- printf("\n%d Additional records.\n\n", additional);
- //in the RFC about DNS is said that QDCOUNT is usally set to 1 but not specified that it is 1. I googled a bit and found http://maradns.samiam.org/multiple.qdcount.html . I will print all questions but need to take care that they have same type.
- char *location = &buf[sizeof(struct DNS_HEADER)];
- if (questions)
- printf("\n\nQuestion records:\n");
- for(i = 0; i < questions; ++i) {
- char *l = parse_query(location);
- location = l;
- }
- /*
- if (answers)
- printf("\n\nAnswer records:\n");
- for(i = 0; i < answers; ++i) {
- location = parse_rr((struct RES_RECORD*)location);
- }
- if (authorities)
- printf("\n\nAuthoritative Servers:\n");
- for (i = 0; i < authorities; ++i) {
- location = parse_rr((struct RES_RECORD*)location);
- }
- if (additional)
- printf("\n\nAdditional records:\n");
- for (i = 0; i < additional; ++i) {
- location = parse_rr((struct RES_RECORD*)location);
- }*/
- }
- void hexDump(char *desc, void *addr, int len) {
- int i;
- unsigned char buff[17];
- unsigned char *pc = addr;
- if(desc != NULL)
- printf("%s:\n", desc);
- for(i=0; i<len; i++) {
- if(i!=0 && i%8==0)printf(" ");
- if((i % 16) == 0) {
- if(i != 0)
- printf(" %s\n", buff);
- printf(" %04x ", i);
- }
- printf(" %02x", pc[i]);
- if((pc[i] < 0x20) || (pc[i] > 0x7e))
- buff[i % 16] = '.';
- else
- buff[i % 16] = pc[i];
- buff[(i % 16) + 1] = '\0';
- }
- while((i % 16) != 0) {
- printf(" ");
- i++;
- }
- printf(" %s\n", buff);
- }
Advertisement
Add Comment
Please, Sign In to add comment