- 論壇徽章:
- 0
|
Linux下的地址解析函數(shù)應(yīng)用實(shí)例
作者: 默難 (
monnand@gmail.com
)
0 引言
域名系統(tǒng)(DNS)是一種用于TCP/IP應(yīng)用程序的分布式數(shù)據(jù)庫(kù), 它提供主機(jī)名字和IP地址之間的轉(zhuǎn)換及有關(guān)電子郵件的選路信息.[1] 目前, 它已經(jīng)在全球范圍內(nèi)被廣泛應(yīng)用. 從應(yīng)用的角度上看, 對(duì)DNS的訪問(wèn)是通過(guò)一個(gè)地址解析器(resolver)來(lái)完成的. 本文通過(guò)講解一些常用的地址解析函數(shù), 并利用精簡(jiǎn)后的部分qmail代碼, 讓不熟悉DNS相關(guān)函數(shù)的程序員了解并掌握常用的地址解析函數(shù).
1 概述
DNS查詢中, 最常用的兩類(lèi)分別是A類(lèi)查詢(A query)和指針查詢(PTR query). 前者是已知主機(jī)名, 詢問(wèn)IP; 后者是已知IP, 詢問(wèn)主機(jī)名. 對(duì)于這些查詢, 在Unix主機(jī)中可以直接調(diào)用基本DNS函數(shù): gethostbyname(3)和gethostbyaddr(3)來(lái)實(shí)現(xiàn). 但是對(duì)于其他類(lèi)型的查詢(例如MX查詢), 則沒(méi)有專(zhuān)門(mén)的函數(shù)來(lái)負(fù)責(zé)處理. 此時(shí), 程序員不得不依賴地址解析函數(shù)來(lái)親自處理這些問(wèn)題. 這需要對(duì)DNS報(bào)文格式有基本的了解, 這些將在下面幾節(jié)進(jìn)行說(shuō)明. 關(guān)于gethostbyname(3)和gethostbyaddr(3)兩個(gè)函數(shù), 讀者可以查閱自己系統(tǒng)上的man手冊(cè).
2 DNS報(bào)文格式
在對(duì)地址解析函數(shù)講解之前, 有必要先了解一下DNS報(bào)文格式. 之后的幾節(jié)會(huì)頻繁地涉及到本節(jié)所講的內(nèi)容. 如果想對(duì)DNS相關(guān)協(xié)議有更深的了解, 可以閱讀參考文獻(xiàn)[1] [2] [3].
DNS定義了一個(gè)用于查詢和響應(yīng)的報(bào)文格式, 圖1 顯示了這個(gè)報(bào)文的總體格式.
[圖1]
![]()
每個(gè)DNS查詢(或響應(yīng))報(bào)文都包含有一個(gè)12字節(jié)長(zhǎng)的首部和四個(gè)變長(zhǎng)的字段組成.
對(duì)于本文來(lái)說(shuō), 首部中主要關(guān)心的是問(wèn)題數(shù)和資源記錄數(shù)兩個(gè)字段. 這兩個(gè)字段分別用于說(shuō)明各自對(duì)應(yīng)的變長(zhǎng)字段中的條目數(shù). 問(wèn)題數(shù)說(shuō)明查詢問(wèn)題字段中的條目數(shù); 資源記錄數(shù)則說(shuō)明回答字段中的條目數(shù). 對(duì)于一個(gè)DNS查詢報(bào)文, 問(wèn)題數(shù)通常是1. 對(duì)于應(yīng)答報(bào)文, 回答數(shù)至少是1.
首部以下是四個(gè)變長(zhǎng)字段, 本文所關(guān)心的是查詢問(wèn)題字段和回答字段.
查詢問(wèn)題字段可以包含多個(gè)查詢問(wèn)題, 每個(gè)問(wèn)題的格式如圖2 所示.
[圖2]
![]()
其中, 查詢名一項(xiàng)存儲(chǔ)著要查找的名字. 它長(zhǎng)度可變并以一種特殊的格式存儲(chǔ). 程序可以通過(guò)其中存儲(chǔ)的內(nèi)容確定其長(zhǎng)度. 具體獲得其中存儲(chǔ)內(nèi)容的方法, 將在下一節(jié)中進(jìn)行詳細(xì)講解. 每一個(gè)問(wèn)題有一個(gè)查詢類(lèi)型, 每個(gè)響應(yīng)(下文中將會(huì)提到)也同樣有一個(gè)類(lèi)型. 常用的類(lèi)型有: A類(lèi)型---表示期望獲得查詢名的IP地址; PTR查詢---表示期望獲得一個(gè)IP地址對(duì)應(yīng)的域名; MX查詢---郵件交換查詢(關(guān)于MX查詢的具體內(nèi)容, 下文會(huì)提到). 查詢類(lèi)指定了所使用的協(xié)議簇, 通常是1, 表示Internet地址.
回答字段可以包含多個(gè)條目. 每個(gè)回答字段是以一種叫做資源記錄(Resource Record, RR)的格式存儲(chǔ)的. ( 授權(quán)字段和額外信息字段也同樣以資源記錄的格式存儲(chǔ)信息). 資源記錄的格式如圖3 所示.
[圖3]
![]()
域名是記錄中資源數(shù)據(jù)對(duì)應(yīng)的名字. 它的格式和前面介紹的查詢名字段格式相同. 類(lèi)型和類(lèi)字段和前面介紹的查詢類(lèi)型, 查詢類(lèi)字段的功能一樣. 類(lèi)字段的取值通常是1, 表示Internet地址. 生存時(shí)間字段是客戶程序保留該資源記錄的秒數(shù). 資源數(shù)據(jù)長(zhǎng)度說(shuō)明資源數(shù)據(jù)包含的字節(jié)數(shù). 資源數(shù)據(jù)則根據(jù)類(lèi)型字段的值有不同的格式. 對(duì)于A類(lèi)型, 資源數(shù)據(jù)是IP地址. 對(duì)于MX查詢, 資源數(shù)據(jù)是優(yōu)先值和域名, 域名的格式與查詢名字段格式相同(MX記錄的具體內(nèi)容下文會(huì)有介紹).
至此, DNS中用到的報(bào)文格式已經(jīng)基本介紹完. 下一節(jié)中將會(huì)介紹一些常用的地址解析函數(shù). 閱讀下文時(shí), 最好隨時(shí)翻閱本節(jié)所講的內(nèi)容以便于理解.
3 地址解析函數(shù)
除了經(jīng)常用到的gethostbyname(3)和gethostbyaddr(3)函數(shù)以外, Linux(以及其它UNIX/UNIX-like系統(tǒng))還提供了一套用于在底層處理DNS相關(guān)問(wèn)題的函數(shù)(這里所說(shuō)的底層僅是相對(duì)gethostbyname和gethostbyaddr兩個(gè)函數(shù)而言). 這套函數(shù)被稱(chēng)為地址解析函數(shù)(resolver functions). 用戶可以通過(guò)鍵入man resolver來(lái)了解其中的具體信息. 這里將對(duì)其中常用到的函數(shù)做一個(gè)解釋. 常用的地址解析函數(shù)原型如下:
#include
#include
#include
extern struct state _res;
int res_init(void);
int res_query(const char *dname, int class, int type,
unsigned char *answer, int anslen);
int res_search(const char *dname, int class, int type,
unsigned char *answer, int anslen);
int dn_expand(unsigned char *msg, unsigned char *eomorig,
unsigned char *comp_dn, unsigned char *exp_dn,
int length);
_res: 這個(gè)結(jié)構(gòu)體用于保存相關(guān)的狀態(tài)信息. 它的定義在中.
res_init: 讀取配置文件并修改環(huán)境變量:LOCALDOMAIN. 在調(diào)用其他地址解析函數(shù)前通常要先調(diào)用res_init. 如果執(zhí)行成功, 函數(shù)返回0; 否則返回-1.
res_query: 用來(lái)發(fā)出一個(gè)指定類(lèi)(由參數(shù)class指定)和類(lèi)型(由參數(shù)type指定)的DNS詢問(wèn). dname是要查詢的主機(jī)名. 返回信息被存儲(chǔ)在answser指向的內(nèi)存區(qū)域中. 信息的長(zhǎng)度不能大于anslen個(gè)字節(jié). 這個(gè)函數(shù)會(huì)創(chuàng)建一個(gè)DNS查詢報(bào)文并把它發(fā)送到指定的DNS服務(wù)器.
res_search: 和res_query的行為類(lèi)似, 與res_query不同的是, 當(dāng)域名中不包含點(diǎn)時(shí), 會(huì)在域名后面加上默認(rèn)域名; 同時(shí), 支持遞歸查詢(即當(dāng)一個(gè)服務(wù)器沒(méi)有存儲(chǔ)詢問(wèn)的信息時(shí), 會(huì)繼續(xù)向其他服務(wù)器詢問(wèn)). 一般情況下盡量使用res_search. 因?yàn)樗某晒茁蕰?huì)比較大.
res_query和res_search函數(shù)返回值是響應(yīng)報(bào)文的長(zhǎng)度; 如果發(fā)生錯(cuò)誤則返回-1.
dn_expand: 上一節(jié)中已經(jīng)說(shuō)到, DNS報(bào)文中主機(jī)名是以一種特殊格式存儲(chǔ)的. dn_expand函數(shù)則是將這種特殊格式存儲(chǔ)的字符串還原成一般格式. msg參數(shù)值是整個(gè)DNS報(bào)文的首地址; eomorig參數(shù)指向DNS報(bào)文的最后一個(gè)字節(jié)后的一字節(jié), 用于指定報(bào)文的結(jié)束位置; comp_dn參數(shù)指向報(bào)文中需要被還原的主機(jī)名的首地址; 還原后的主機(jī)名被存儲(chǔ)在exp_dn指向的內(nèi)存區(qū)域中, 長(zhǎng)度不大于length個(gè)字節(jié). 函數(shù)返回主機(jī)名在DNS報(bào)文中的長(zhǎng)度(即被還原前的長(zhǎng)度); 如果發(fā)生錯(cuò)誤則返回-1.
需要注意的是, 如果程序中用到了這些地址解析函數(shù), 那么在編譯的時(shí)候需要加上-lresolv選項(xiàng)才能正常編譯.
利用這些地址解析函數(shù), 不僅可以完成A類(lèi)查詢或PTR查詢, 還可以進(jìn)行其他類(lèi)型的詢問(wèn). 下一節(jié)將給出利用地址解析函數(shù)進(jìn)行MX查詢的實(shí)例.
4 地址解析函數(shù)應(yīng)用實(shí)例---MX查詢
在發(fā)送電子郵件時(shí), 需要用到MX(Mail eXchange)記錄. 一個(gè)電子郵箱的地址是 "用戶名@域名" 的格式. 當(dāng)要給某個(gè)用戶發(fā)送電子郵件時(shí), 首先需要從這個(gè)用戶的電子郵箱地址中得到域名; 然后向DNS服務(wù)器發(fā)出一個(gè)MX查詢, 詢問(wèn)該域名由哪些服務(wù)器負(fù)責(zé)處理.DNS服務(wù)器會(huì)返回處理該域名的服務(wù)器的主機(jī)名. 每個(gè)主機(jī)名對(duì)應(yīng)一個(gè)16bit的整數(shù)值, 該值稱(chēng)為優(yōu)先值(preference value), 如果一個(gè)域存在多條MX記錄, 則首先使用優(yōu)先值較小的主機(jī)名. 之后, 就是利用SMTP協(xié)議與相應(yīng)的主機(jī)進(jìn)行連接并發(fā)送郵件.
如果要發(fā)出一個(gè)MX查詢, 可以利用host命令:
[monnand@monnand-host ~]$ host -t mx gmail.com
gmail.com mail is handled by 50 gsmtp183.google.com.
gmail.com mail is handled by 5 gmail-smtp-in.l.google.com.
gmail.com mail is handled by 10 alt1.gmail-smtp-in.l.google.com.
gmail.com mail is handled by 10 alt2.gmail-smtp-in.l.google.com.
gmail.com mail is handled by 50 gsmtp163.google.com.
-t 選項(xiàng)用于指明查詢類(lèi)型, -t mx表示發(fā)起一個(gè)MX查詢. 后面的參數(shù)是要查詢的域名(這里以gmail.com為例).
顯示出的是關(guān)于查詢域名的MX記錄. 這里關(guān)于gmail.com的MX記錄共5條, 每條記錄都有相應(yīng)的優(yōu)先值(顯示在主機(jī)名前面), 例如第一條記錄的優(yōu)先值是50.
下面, 我們就利用前面講到的地址解析函數(shù)來(lái)實(shí)現(xiàn)一個(gè)類(lèi)似功能的程序. 即指定查詢域名, 打印出關(guān)于這個(gè)域名的MX記錄. 該程序的代碼是從qmail的代碼中精簡(jiǎn)出來(lái)的, 其中去掉了一些錯(cuò)誤檢測(cè), 并修改了與qmail其他部分相關(guān)聯(lián)的代碼, 使整個(gè)程序能夠獨(dú)立出來(lái)(當(dāng)然, 因?yàn)槿サ袅撕芏噱e(cuò)誤檢測(cè), 程序也失去了原有的健壯性和安全性). 但是整體的思路基本沒(méi)有大的改動(dòng). 有興趣的讀者可以自己閱讀qmail的源代碼. 相信會(huì)有更多的收獲.
整個(gè)程序被寫(xiě)到了兩個(gè)文件中, 分別名為dns.h和dns.c.
以下是dns.h中的內(nèi)容:
1 #ifndef DNS_H
2 #define DNS_H
3
4 #define DNS_MSG_END -2
5
6 #define dns_mx_query(str) dns_resolve((str),T_MX)
7 #define dns_mx_expand() dns_findmx(T_MX)
8
9 #define foreach_mxrr(p,dn) while(dns_mx_expand()!=DNS_MSG_END \
10 &&(!dns_get_mxrr(&p,dn,MAXDNAME)))
11
12 void dns_init(void);
13 int dns_get_mxrr(unsigned short *,unsigned char *,unsigned int);
14 int dns_resolve(char *,int);
15 int dns_findmx(int);
16
17 #endif /* #ifndef MONNAND_DNS_H */
該文件中聲明了4個(gè)函數(shù). 為了便于操作, 定義了三個(gè)宏. 關(guān)于其中具體的用法, 之后會(huì)有介紹. 下面給出dns.c中的源代碼:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10
11 #include "dns.h"
12
13 extern int res_query();
14 extern int res_search();
15 extern int errno;
16 extern int h_errno;
17
18 static unsigned short getshort(unsigned char *c) { unsigned short u; u = c[0]; return (u = sizeof(response))
39 responselen = sizeof(response);
40 responseend = response.buf + responselen;
41 responsepos = response.buf + sizeof(HEADER);
42 n = ntohs(response.hdr.qdcount);
43 while(n-->0)
44 {
45 i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
46 responsepos += i;
47 i = responseend - responsepos;
48 if(i
注釋:
18: getshort函數(shù)從指定地址讀取16bit網(wǎng)絡(luò)字節(jié)順序的數(shù)據(jù), 并將其轉(zhuǎn)換成little-endian的順序返回.
20: 定義了一個(gè)聯(lián)合體變量名為response, 用于存儲(chǔ)DNS響應(yīng)報(bào)文. HEADER是用于存儲(chǔ)DNS首部的結(jié)構(gòu)體, 定義在中(通常在/usr/include/arpa/nameser_compat.h中. 這個(gè)頭文件則在中被include. 后面用到的很多宏都定義在這個(gè)頭文件中). HEADER結(jié)構(gòu)體中本文會(huì)用到的成員是dncount和ancout, 分別表示問(wèn)題數(shù)和資源記錄數(shù)(參見(jiàn)圖1).PACKETSZ也定義在中, 這個(gè)宏表示一個(gè)報(bào)文的最大長(zhǎng)度.
21-26: responselen是響應(yīng)報(bào)文的長(zhǎng)度. responseend指向了響應(yīng)報(bào)文最后一個(gè)字節(jié)之后的一字節(jié), 即response.buf+responselen. responsepos指向了即將處理的字段. numanswers是還未處理的回答數(shù). name用來(lái)存儲(chǔ)主機(jī)名, 長(zhǎng)度是MAXDNAME個(gè)字節(jié). MAXDNAME定義在中, 表示域名的最大長(zhǎng)度. pref用來(lái)存儲(chǔ)MX記錄的優(yōu)先值.
28: dns_resolve函數(shù)發(fā)起一個(gè)指定查詢名(domain)和查詢類(lèi)型(type)的DNS查詢. type可取的值在中定義成了宏. 這些宏都是以T_開(kāi)頭. 例如, A類(lèi)查詢的值是T_A. 對(duì)于MX查詢, 則可以調(diào)用dns_resolve(domain,T_MX)(這也就是dns.h中, dns_mx_query這個(gè)宏所做的). 如果發(fā)生錯(cuò)誤, 函數(shù)返回-1, 否則返回資源記錄數(shù)(參見(jiàn)圖1).
35: 利用res_search函數(shù)發(fā)起一條指定類(lèi)型的DNS查詢. 其中的參數(shù)C_IN表示Internet地址. C_IN這個(gè)宏也定義在中. 返回值賦給responselen, 即響應(yīng)報(bào)文長(zhǎng)度.
36: 檢查是否有錯(cuò)誤發(fā)生, 如果發(fā)生返回-1. 實(shí)際上這種錯(cuò)誤檢測(cè)是不完善的. 關(guān)于詳細(xì)的錯(cuò)誤檢測(cè)方法可以參考qmail源代碼中的dns.c文件.
40-42: 調(diào)整responseend和responsepos的值. 并將報(bào)文中的問(wèn)題數(shù)存儲(chǔ)在臨時(shí)變量n中, 用于之后的處理. 由于響應(yīng)報(bào)文中的數(shù)據(jù)都是網(wǎng)絡(luò)字節(jié)順序, 因此需要調(diào)用ntohs函數(shù)進(jìn)行轉(zhuǎn)換. ntohs函數(shù)的具體內(nèi)容可以參考man手冊(cè).調(diào)整后, responsepos指向第一個(gè)查詢問(wèn)題的首地址.
43-50: 跳過(guò)所有的查詢問(wèn)題, 讓responsepos指向第一個(gè)回答的首地址. 此時(shí), 需要參考第二節(jié)中的內(nèi)容來(lái)幫助理解. 首先利用dn_expand函數(shù)獲得查詢問(wèn)題字段中查詢名的長(zhǎng)度, 并把該值賦給i. 之后, responsepos+=i使得responsepos指向了查詢類(lèi)型字段的首地址(參見(jiàn)圖2). QFIXEDSZ宏定義在中, 其值等于4. 它表示DNS查詢報(bào)文中問(wèn)題部分的定長(zhǎng)字段的字節(jié)數(shù), 即查詢類(lèi)型和查詢類(lèi)兩個(gè)字段的總長(zhǎng)度. i = responseend - responsepos令i的值等于responsepos和responseend之間的距離, 由于此時(shí)responsepos指向問(wèn)題部分查詢類(lèi)型的第一個(gè)字節(jié), 因此, 對(duì)于一個(gè)正常的報(bào)文來(lái)說(shuō), i的值應(yīng)該至少等于4. 因此, 在第48行進(jìn)行了檢測(cè), 若i
55: dns_findmx函數(shù)用于在調(diào)用了dns_resolve函數(shù)之后, 分析DNS響應(yīng)報(bào)文中的回答字段. 如果當(dāng)前responsepos指向的回答字段的類(lèi)型是參數(shù)wanttype指定的類(lèi)型, 則對(duì)該回答字段進(jìn)行處理. 參數(shù)wanttype可取的值與dns_resolve函數(shù)中的type參數(shù)可取值一樣. 對(duì)于MX記錄, 值為T(mén)_MX. dns.h中dns_mx_expand宏的定義就是dns_findmx(T_MX). 該函數(shù)若發(fā)生錯(cuò)誤則返回-1, 若報(bào)文中已經(jīng)沒(méi)有可以處理的字段, 則返回DNS_MSG_END. 否則返回name數(shù)組存儲(chǔ)的字符串長(zhǎng)度(不包括結(jié)尾的'\0').
61-62: 檢查未處理的回答字段數(shù)目, 若達(dá)到或小于零, 則返回DNS_MSG_END. 否則numanswers值減一.
64: 回答字段是以資源記錄格式存儲(chǔ)的. 第一項(xiàng)是域名(參見(jiàn)圖3). 因此用dn_expand函數(shù)將該字段還原為普通字符串格式. 并將返回的該字段長(zhǎng)度賦值給i.
66: 調(diào)整responsepos的值, 使其跳過(guò)域名部分, 指向類(lèi)型字段(參見(jiàn)圖3).
67-68: 資源記錄中, 定長(zhǎng)字段的總長(zhǎng)度為10字節(jié),即類(lèi)型, 類(lèi), 生存時(shí)間和資源數(shù)據(jù)長(zhǎng)度字段的總長(zhǎng)度(參見(jiàn)圖3). 若responseend-responsepos的值小于10, 則表明該報(bào)文非法.
69-71: 此時(shí)responsepos指向了資源記錄中類(lèi)型字段的首地址. 利用getshort函數(shù)分別獲得類(lèi)型和資源數(shù)據(jù)長(zhǎng)度字段的值, 存儲(chǔ)在rrtype和rrdlen變量中. 之后,調(diào)整responsepos的值, 使其指向資源數(shù)據(jù)的首地址(參見(jiàn)圖3). 對(duì)于一個(gè)MX查詢, 資源數(shù)據(jù)中的內(nèi)容是優(yōu)先值和主機(jī)名.
72-82: 如果這條資源記錄的類(lèi)型是函數(shù)參數(shù)所指定的類(lèi)型, 則對(duì)其進(jìn)行處理. MX記錄中, 資源數(shù)據(jù)內(nèi)第一項(xiàng)存儲(chǔ)著16bit的優(yōu)先值, 之后存儲(chǔ)著主機(jī)名. 優(yōu)先值長(zhǎng)度為2字節(jié), 主機(jī)名長(zhǎng)度至少1字節(jié), 則資源數(shù)據(jù)長(zhǎng)度至少要3字節(jié). 否則報(bào)文格式為非法. 第74, 75行就是利用這種方法檢測(cè)資源數(shù)據(jù)是否為非法. 第76行從資源數(shù)據(jù)中獲得優(yōu)先值存儲(chǔ)在pref中. 由于報(bào)文中的優(yōu)先值是按照網(wǎng)絡(luò)字節(jié)順序存儲(chǔ)的, 因此需要將其轉(zhuǎn)換成little-endian順序后存到pref中. 接著對(duì)name數(shù)組清零. 之后從資源數(shù)據(jù)中提取主機(jī)名. responsepos+=rrdlen令responsepos指向了下一條資源數(shù)據(jù). 最后利用strlen函數(shù)返回主機(jī)名的字符串長(zhǎng)度.
83: 該資源記錄的類(lèi)型與參數(shù)指定類(lèi)型不符, 則跳過(guò)該條記錄, 將responsepos調(diào)整至下一條資源記錄.
87-91: 調(diào)用res_init函數(shù)執(zhí)行相關(guān)初始化操作. 并對(duì)name數(shù)組清零. 此處沒(méi)有對(duì)res_init的返回值進(jìn)行檢測(cè).
93-100: dns_get_mxrr函數(shù)將pref的值(優(yōu)先值)存儲(chǔ)到p指向的地址中, 并將name中存儲(chǔ)的主機(jī)名復(fù)制到dn指向的地址中, 復(fù)制的長(zhǎng)度不超過(guò)len個(gè)字節(jié). 如果len個(gè)字節(jié)不足以存儲(chǔ)整個(gè)主機(jī)名, 則返回-1, 否則返回0.
102: main函數(shù), argv[1]中會(huì)存儲(chǔ)著要查詢的域名.
104-106: dname用于存儲(chǔ)查找到的主機(jī)名. 變量i用于存儲(chǔ)相關(guān)函數(shù)的返回值. p用于存儲(chǔ)優(yōu)先值.
108-112: 用戶提供的參數(shù)有錯(cuò)誤.
113: 利用dns.h中定義的宏, 發(fā)起MX查詢. 該語(yǔ)句相當(dāng)與i = dns_resolve(argv[1],T_MX);
120: 利用dns.h中定義的宏, 對(duì)響應(yīng)報(bào)文中的每條資源記錄進(jìn)行處理. foreach_mxrr宏在dns.h中定義, 該語(yǔ)句相當(dāng)于while(dns_findmx(T_MX)!=DNS_MSG_END&&(!dns_get_mxrr(&p,dname,MAXDNAME)))
121-124: 打印每條資源記錄后函數(shù)返回.
該程序在Magic Linux 2.0正式版上編譯成功( 內(nèi)核版本2.6.15.3; gcc版本3.4.4; i386體系結(jié)構(gòu) ).編譯和運(yùn)行結(jié)果如下:
[monnand@monnand-host src]$ gcc -lresolv dns.c -o dns
[monnand@monnand-host src]$ ./dns gmail.com
pref domain name
50 gsmtp163.google.com
50 gsmtp183.google.com
5 gmail-smtp-in.l.google.com
10 alt1.gmail-smtp-in.l.google.com
10 alt2.gmail-smtp-in.l.google.com
5 后記
本文簡(jiǎn)要介紹了DNS報(bào)文格式, 講解了常用的地址解析函數(shù)并給出了這些函數(shù)的應(yīng)用實(shí)例. 第4節(jié)中的代碼可以應(yīng)用在其他程序內(nèi), 但是使用前最好對(duì)其進(jìn)行一定的修改從而增強(qiáng)健壯性和安全性. 修改時(shí)可以參考qmail的源代碼中dns.c和dns.h兩個(gè)文件. 如果想了解更多的地址解析函數(shù), 可以查閱man resolver. 如果想對(duì)DNS相關(guān)的協(xié)議及報(bào)文格式有更深的了解, 可以查閱附錄中的參考文獻(xiàn).
附錄 參考文獻(xiàn)
[1]W. Richard Stevens.TCP/IP詳解 卷1:協(xié)議.北京:機(jī)械工業(yè)出版社.1993.
[2]Mockapetris, P. V. "Domain Names: Concepts and Facilities," RFC 1034. 1987
[3]Mockapetris, P. V. "Domain Names: Implementation and Specification," RFC1035. 1987
本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:
http://blog.csdn.net/monnand/archive/2006/07/15/924731.aspx
本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u2/86948/showart_2059830.html |
|