DNS客户端改进版
whitebear
对[link2post id=”797″]上一个DNS客户端[/link2post]的简单改进。稍微封装了一下,同时修改了接收返回部分的代码,可以读到被GFW劫持域名的正确记录。
<br></br>#include <stdio.h><br></br>#include <stdlib.h><br></br>#include <string.h><br></br>#include <strings.h></strings.h></string.h></stdlib.h></stdio.h>
#include
#include
#include
#include <netdb.h>
#include <unistd.h></unistd.h></netdb.h>
#define DNSSERVER (“8.8.8.8”)
extern int errno;
struct DNSHeader{
short TranscationID;
short Flags;
short Questions;
short AnswerRRs;
short AuthorityRRs;
short AdditionalRRs;
}__attribute__((packed));
struct DNSQuery{
short Type;
short Class;
}__attribute__((packed));
struct DNSQueryFull{
char* domain;
short Type;
short Class;
}__attribute__((packed));
struct DNSAnswerRR{
short Name;
short Type;
short Class;
int TTL;
short Length;
int Address;
}__attribute__((packed));
int parseresponse(void *buffer){
struct DNSHeader *responseheader = (struct DNSHeader*)buffer;
printf(“TranscationID = 0x%x\n”, ntohs(responseheader->TranscationID));
printf(“Flags = 0x%x\n”, ntohs(responseheader->Flags));
printf(“Questions = %d\n”, ntohs(responseheader->Questions));
printf(“AnswerRRs = %d\n”, ntohs(responseheader->AnswerRRs));
printf(“AuthorityRRs = %d\n”, ntohs(responseheader->AuthorityRRs));
printf(“AdditionalRRs = %d\n”, ntohs(responseheader->AdditionalRRs));
char tmp;
char *ptmp = buffer + sizeof(struct DNSHeader);
tmp = *ptmp++;
printf(“domainlen = %d\n”, tmp);
ptmp += tmp;
tmp = *ptmp++;
printf(“extlen = %d\n”, tmp);
ptmp += tmp;
ptmp++;
struct DNSQuery *responsequery = (struct DNSQuery*)ptmp;
printf(“Type = %x\n”, ntohs(responsequery->Type));
printf(“Class = %x\n”, ntohs(responsequery->Class));
ptmp += 4;
for(int i = 0; i AnswerRRs); i++){
printf("********** Record %d **********\n", i + 1);
struct DNSAnswerRR *answer = (struct DNSAnswerRR*)ptmp;
printf(“Name = 0x%x\n”, ntohs(answer->Name));
printf(“Type = 0x%x\n”, ntohs(answer->Type));
printf(“Class = 0x%x\n”, ntohs(answer->Class));
printf(“TTL = %d\n”, ntohl(answer->TTL));
printf(“Length = %d\n”, answer->Length);
struct in_addr addr;
addr.s_addr = answer->Address;
printf(“IP = %s\n”, inet_ntoa(addr));
ptmp += sizeof(struct DNSAnswerRR);
}
return 0;
}
int buildrequest(
const char *domain, const char *ext, void *dnspacket){
struct DNSHeader header;
bzero(&header, sizeof(header));
FILE *fp = fopen("/dev/random", “rb”);
short randomnum = 0;
fread(&randomnum, 1, sizeof(header.TranscationID), fp);
fclose(fp);
header.TranscationID = htons(randomnum);
header.Flags = htons(0x0100);
header.Questions = htons(1);
struct DNSQuery query;
bzero(&query, sizeof(query));
query.Type = htons(1);
query.Class = htons(1);
char domainsize = sizeof(char) * strlen(domain);
char extsize = sizeof(char) * strlen(ext);
int dnspacketsize = sizeof(header) + sizeof(query) +
domainsize + sizeof(domainsize) + extsize + sizeof(extsize) + 1;
if(dnspacket == NULL) return dnspacketsize;
bzero(dnspacket, sizeof(dnspacket));
memcpy(dnspacket, &header, sizeof(header));
int domainsizeoffset = sizeof(header);
memcpy(dnspacket + domainsizeoffset, &domainsize, sizeof(domainsize));
int domainoffset = domainsizeoffset + sizeof(domainsize);
memcpy(dnspacket + domainoffset, domain, domainsize);
int extsizeoffset = domainoffset + domainsize;
memcpy(dnspacket + extsizeoffset, &extsize, sizeof(extsize));
int extoffset = extsizeoffset + sizeof(extsize);
memcpy(dnspacket + extoffset, ext, extsize);
int queryoffset = extoffset + extsize + 1;
memcpy(dnspacket + queryoffset, &query, sizeof(query));
return dnspacketsize;
}
int main(int argc, const char **argv){
if(argc != 3){
printf(“Usage: %s domainname extname\n”, argv[0]);
return 0;
}
const char *domain = argv[1];
const char *ext = argv[2];
struct servent *dnsserv;
if((dnsserv = getservbyname(“domain”, “udp”)) == NULL){
fprintf(stderr, “getservbyname(): failed to find domain service info.\n”);
return -1;
}
struct sockaddr_in remoteaddr;
remoteaddr.sin_family = PF_INET;
if((remoteaddr.sin_addr.s_addr = inet_addr(DNSSERVER)) == -1){
perror(“inet_addr()”);
return -1;
}
remoteaddr.sin_port = dnsserv->s_port;
struct protoent *proto;
if((proto = getprotobyname(“udp”)) == NULL){
fprintf(stderr, “getprotobyname(): failed to find udp protocol info\n”);
return -1;
}
int sockfd = -1;
if((sockfd = socket(PF_INET, SOCK_DGRAM, proto->p_proto))