成人AV在线无码|婷婷五月激情色,|伊人加勒比二三四区|国产一区激情都市|亚洲AV无码电影|日av韩av无码|天堂在线亚洲Av|无码一区二区影院|成人无码毛片AV|超碰在线看中文字幕

DNS數(shù)據(jù)包解析

仔細(xì)看了看DNS 協(xié)議的相關(guān)東西,其實(shí)實(shí)際編程的時(shí)候根本用不到DNS 細(xì)節(jié)的東西,要獲取域名的時(shí)候經(jīng)終端下用host 或者nslookup 指令就可以,在c 里面使用gethostbyname 或者g

仔細(xì)看了看DNS 協(xié)議的相關(guān)東西,其實(shí)實(shí)際編程的時(shí)候根本用不到DNS 細(xì)節(jié)的東西,要獲取域名的時(shí)候經(jīng)終端下用host 或者nslookup 指令就可以,在c 里面使用

gethostbyname 或者getaddrinfo 都能很輕松得將dns 域名解析為ip 地址,寫這個(gè)純粹出于個(gè)人興趣,或者說是閑得吧。

在進(jìn)行域名解析的時(shí)候,解析程序向域名服務(wù)器發(fā)起請(qǐng)求,域名服務(wù)器也就是在操作系統(tǒng)網(wǎng)絡(luò)配置的時(shí)候?qū)戇M(jìn)去的那個(gè)DNS 服務(wù)器地址,或者也有可能是由ISP 提供的自動(dòng)獲取的,原理都一樣,域名服務(wù)器收到請(qǐng)求后進(jìn)行處理,首先在本地緩存中查找對(duì)應(yīng)的域名,找到后將IP 地址直接返回,找不到就向其它的授權(quán)服務(wù)器請(qǐng)求數(shù)據(jù),又可以分為著名的遞歸查詢和非遞歸查詢。

遞歸查詢就是說自始至終都由一臺(tái)域名服務(wù)器進(jìn)行查詢,它在自己這里找不到的時(shí)候會(huì)向其它的域名服務(wù)器請(qǐng)求并且獲取數(shù)據(jù),然后返回給請(qǐng)求方。

非遞歸查詢是指域名服務(wù)器收到請(qǐng)求后,如果自己有這個(gè)域名的信息就返回,如果沒有就返回其它域名服務(wù)器的指針,請(qǐng)求方再根據(jù)這些域名服務(wù)器再發(fā)起查詢。

按自己的理解瞎扯了一通,也不知道準(zhǔn)不準(zhǔn)確,關(guān)于DNS 的相關(guān)資料網(wǎng)上有的是,中文的都大批大批的。

DNS 服務(wù)器的原理其實(shí)沒什么好說的,每天都在跟DNS 打交道,但DNS 的協(xié)議在實(shí)現(xiàn)上還是稍微有點(diǎn)意思的,本來想寫個(gè)程序來測(cè)試一個(gè)我所了解的DNS 協(xié)議,后來在寫的時(shí)候還真發(fā)現(xiàn)一個(gè)小問題,DNS 域名有時(shí)候會(huì)是一個(gè)主域名的別名,比如www.baidu.com ,它就是www.a.shifen.com 這個(gè)域名的別名,在DNS 請(qǐng)求發(fā)送過去之后,response 里面會(huì)有一個(gè)類型為CNAME 的Answers 項(xiàng),里面包含了主域名的相關(guān)信息(其實(shí)也就是主域名的名稱和TTL) ,在這個(gè)應(yīng)答消息里面可能會(huì)出現(xiàn)多個(gè)域名消息,比如每個(gè)Answers 的第一

,

個(gè)字段就是一個(gè)域名,當(dāng)然為了減少數(shù)據(jù)包的容量,DNS 系統(tǒng)對(duì)域名進(jìn)行了壓縮,同一個(gè)域名只會(huì)出現(xiàn)一次,其它的時(shí)候再出現(xiàn)的話就會(huì)用一個(gè)DNS 指針表示。

比如域名:www.baidu.com 在數(shù)據(jù)包中的表示是03 77 77 77 05 62 61 69 64 75 03 63 6f 6d 00

粗體的是長度,將域名中的點(diǎn)去掉,用長度來分隔域名,以0結(jié)束。DNS 允許的長度為0-63個(gè)字節(jié),所以一個(gè)8位的長度最高兩位都為0。

而如果此處域名重復(fù)出現(xiàn),信令中便會(huì)用DNS 指針代替長度,指針為兩個(gè)字節(jié),16位的最位都為1,剩下的14位表示在在整個(gè)數(shù)據(jù)包中的偏移量,當(dāng)程序讀取到c00c 的時(shí)候很容易判斷它是一個(gè)指針而不是一個(gè)長度字段,于是根據(jù)c00c 指向的領(lǐng)移量,即從數(shù)據(jù)包開始后的第12個(gè)字節(jié),跳轉(zhuǎn)過去讀取出域名信息。

#include

#include

#include

#include

#include

#include

#include

#include

#define DNS_SVR "211.68.71.4"

,

#define DNS_HOST 0x01

#define DNS_CNAME 0x05

int socketfd;

struct sockaddr_in dest;

static void

send_dns_request(const char *dns_name);

static void

parse_dns_response();

/**

* Generate DNS question chunk */

static void

generate_question(const char *dns_name , unsigned char *buf , int *len);

/**

* Check whether the current byte is * a dns pointer or a length

,

*/

static int

is_pointer(int in);

/**

* Parse data chunk into dns name

* @param chunk The complete response chunk

* @param ptr The pointer points to data

* @param out This will be filled with dns name

* @param len This will be filled with the length of dns name */

static void

parse_dns_name(unsigned char *chunk , unsigned char *ptr , char *out , int *len);

int main(int argc , char *argv[]){

if(argc != 2){

printf("Usage : s n" , argv[0]); exit(-1);

}

socketfd = socket(AF_INET , SOCK_DGRAM , 0);

,

if(socketfd < 0){

perror("create socket failed"); exit(-1);

}

bzero(&dest , sizeof(dest));

dest.sin_family = AF_INET;

dest.sin_port = htons(53);

dest.sin_addr.s_addr = inet_addr(DNS_SVR);

send_dns_request(argv[1]);

parse_dns_response();

return 0;

}

static void parse_dns_response(){

unsigned char buf[1024];

unsigned char *ptr = buf;

struct sockaddr_in addr;

char *src_ip;

,

int n , i , flag , querys , answers;

int type , ttl , datalen , len;

char cname[128] , aname[128] , ip[20] , *cname_ptr; unsigned char netip[4];

size_t addr_len = sizeof(struct sockaddr_in);

n = recvfrom(socketfd , buf , sizeof(buf) , 0 , (struct sockaddr*)&addr , &addr_len); ptr = 4; /* move ptr to Questions */

querys = ntohs(*((unsigned short*)ptr));

ptr = 2; /* move ptr to Answer RRs */

answers = ntohs(*((unsigned short*)ptr)); ptr = 6; /* move ptr to Querys */

/* move over Querys */

for(i= 0 ; i < querys ; i ){

for(;;){

flag = (int)ptr[0];

ptr = (flag 1);

if(flag == 0)

break ;

}

ptr = 4;

,

}

printf("-------------------------------n");

/* now ptr points to Answers */

for(i = 0 ; i < answers ; i ){

bzero(aname , sizeof(aname));

len = 0;

parse_dns_name(buf , ptr , aname , &len);

ptr = 2; /* move ptr to Type*/

type = htons(*((unsigned short*)ptr));

ptr = 4; /* move ptr to Time to live */

ttl = htonl(*((unsigned int*)ptr));

ptr = 4; /* move ptr to Data lenth */

datalen = ntohs(*((unsigned short*)ptr));

ptr = 2; /* move ptr to Data*/

if(type == DNS_CNAME){

bzero(cname , sizeof(cname));

len = 0;

parse_dns_name(buf , ptr , cname , &len);

printf("s is an alias for sn" , aname , cname); ptr = datalen;

}

if(type == DNS_HOST){

,

bzero(ip , sizeof(ip));

if(datalen == 4){

memcpy(netip , ptr , datalen);

inet_ntop(AF_INET , netip , ip , sizeof(struct sockaddr)); printf("s has address sn" , aname , ip);

printf("tTime to live: d minutes , d secondsn" , ttl / 60 , ttl 60);

}

ptr = datalen;

}

}

ptr = 2;

}

static void

parse_dns_name(unsigned char *chunk

, unsigned char *ptr , char *out , int *len){

int n , alen , flag;

char *pos = out (*len);

for(;;){

,

flag = (int)ptr[0];

if(flag == 0)

break ;

if(is_pointer(flag)){

n = (int)ptr[1];

ptr = chunk n;

parse_dns_name(chunk , ptr , out , len); break ;

}else{

ptr ;

memcpy(pos , ptr , flag); pos = flag;

ptr = flag;

*len = flag;

if((int)ptr[0] != 0){

memcpy(pos , "." , 1);

pos = 1;

(*len) = 1;

}

}

}

,

}

static int is_pointer(int in){

return ((in & 0xc0) == 0xc0);

}

static void send_dns_request(const char *dns_name){

unsigned char request[256];

unsigned char *ptr = request;

unsigned char question[128];

int question_len;

generate_question(dns_name , question , &question_len);

*((unsigned short*)ptr) = htons(0xff00);

ptr = 2;

*((unsigned short*)ptr) = htons(0x0100);

ptr = 2;

*((unsigned short*)ptr) = htons(1);

ptr = 2;

標(biāo)簽: