A记录及MX记录实现函数参数及配置

查询A记录 (根据域名获取ip)实现

getipbyhost -> gethostbyname //通过域名获取IP地址 – getnameinfo / getaddrinfo

gethostbyname函数实现

域名仅仅是 IP 地址的一个助记符,目的是方便记忆,通过域名并不能找到目标计算机,通信之前必须要将域名转换成 IP 地址。gethostbyname() 函数可以完成这种转换.

需要socket通过域名方式完成连接 , 通过API gethostbyname 函数完成。gethostbyname 函数是 glibc 库中提供一个域名解析的函数。

存在问题:范围结果是 static 类型变量,存在数据被覆盖的情况。

它的原型为:

struct hostent *gethostbyname(const char *name);

入参:字符串name可取的值分为三种类型:

  • 十进制数字格式的IPv4地址
  • 十六进制数字格式的IPv6地址
  • 域名

返回值

返回值为指向struct hostent类型的指针,调用者显然没有提前分配它,那么该结构一定是有内部实现分配的,所以该函数是不可重入的。struct hostent结构定义如下:

struct hostent { 
    char  h_name;            // official name of host 
    char *h_aliases;         // alias list 
    int    h_addrtype;       // host address type 
    int    h_length;         // length of address 
    char *h_addr_list;       // list of addresses  
} 
#define h_addr h_addr_list[0] // for backward compatibility 
  • h_name:代表正式名字
  • h_aliases:指针数组,每个成员指向的字符串代表域名的别名,该数组以NULL结尾
  • h_addrtype:表示解析后的地址类型,可取的值为AF_INET和AF_INET6
  • h_length:地址长度,对于IPv4地址为4,对于IPv6为16字节
  • h_addr_list:指针数组,每个成员指向一个解析出来的IP地址,该数组以NULL结尾
  • h_addr:为了向后兼容,也可以用h_addr引用第一个解析结果

工作原理

gethostbyname(域名->IP)、gethostbyaddr(IP->域名)在解析的时候,系统默认会先到 /etc/hosts 文件中去寻找匹配信息,然后再到DNS服务器去解析,这个顺序是可以交换的,只要修改 /etc/host.conf 里的 host(本机) 和 bind(DNS服务器) 的顺序即可,例:

在DNS服务器配置正常的情况下,gethostbyname的参数为“www.baidu.com”能正常解析,禁掉DNS就不能正常工作了。但是如果把它和 IP 的映射对添加到 /etc/hosts 文件中,则函数又能正常工作了。例如我们在 /etc/hosts 文件里添加这样一组映射:

12.34.56.78                      www.baidu.com

则在执行这两个函数的时候,就会返回映射对对应的信息。

:iHost进行环境配置便是利用的 /etc/hosts里进行绑定

MX记录(邮件交换记录)实现

res_init //读取配置文件/etc/resolv.conf获取默认域名、搜索顺序和名称服务器 地址
res_mkquery //制作标准查询消息 (DNS 数据包)用于名称服务器
res_send //发送查询或更新消息 到名称服务器并检索响应
skipName //points to the answer section
->dn_expand 
skipToData
->skipName
->GETSHORT/GETLONG
dn_expand //将压缩域名扩展为完整域名 

实质:

调用DNS解析器函数实现获取MX记录

DNS解析器

定义

解析器是C库中的一系例程,用于访问DNS系统

解析器主要函数

具体信息请参考手册,man resolver

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 res_querydomain(const char *name, const char *domain, int class, int type, unsigned char *answer, int anslen); 
int res_mkquery(int op, const char *dname, int class, int type, char *data, int datalen, struct rrec *newrr, char *buf, int buflen); 
int res_send(const char *msg, int msglen, char *answer, int anslen);
int dn_comp(unsigned char *exp_dn, unsigned char *comp_dn, int length, unsigned char **dnptrs, unsigned char **lastdnptr); 
int dn_expand(unsigned char *msg, unsigned char *eomorig, unsigned char *comp_dn, char *exp_dn, int length);

1.res_query 发送域查询

参数

domain_name
(输入)指向域名的指针。
.class
(输入)要查找的数据的类。请参阅 res_mkquery() 或  值。
类型 type
(输入)发出的请求的类型。请参阅 res_mkquery() 或  值。
answer_buffer
(输出)指向存储响应的地址的指针。
answer_buffer_length
(输入)答案区域的大小。

2.res_search 搜索域名

参数

domain_name
(输入)指向域名的指针。
.class
(输入)要查找的数据的类。请参阅 res_mkquery() 或  值。
类型 type
(输入)发出的请求的类型。请参阅 res_mkquery() 或  值。
answer_buffer
(输出)指向存储响应的地址的指针。
answer_buffer_length
(输入)答案区域的大小。

3.res_mkquery 将域查询放在缓冲区中

参数

操作 op
(输入)所需的查询操作。这被放入操作码中的 数据包的标头。下面列出了常用值(请参阅  表示所有可能的值):ns_o_query或查询标准查询请求。(此值几乎始终使用)
domain_name
(输入)指向域名称的指针。
.class
(输入)要查找的数据的类。下面列出了常见值 :ns_c_in或C_IN指定 ARPA 互联网。ns_c_any或C_ANY这是通配符匹配。
类型 type
(输入)发出的请求的类型。下面列出了常用值(请参阅  表示所有可能的值):ns_t_a或T_A主机地址。ns_t_aaaa IPv6 地址。ns_t_ns或T_NS权威服务器。ns_t_cname或T_CNAME规范名称。ns_t_soa或T_SOA权限区域的开始。ns_t_wks或T_WKS知名服务。ns_t_ptr或T_PTR域名指针。ns_t_hinfo或T_HINFO主机信息。ns_t_mx或T_MX邮件路由信息。ns_t_txt或T_TXT文本字符串。ns_t_any或T_ANY通配符匹配。
search_data
(输入)包含反向查询数据的缓冲区。它是空的 IQUERY 以外的类型。
search_data_length
(输入)search_data的长度。对于以下类型为空 查询。
保留 reserved
(输入)保留且当前未使用的参数。它始终为空 指针(为兼容性而定义)。
query_buffer
(输出)指向包含查询的用户提供的位置的指针 消息。
query_buffer_length
(输入)query_buffer的长度。

4.res_send 发送缓冲域查询或更新

参数

query_buffer
(输入)指向查询或更新消息的指针。

query_buffer_length
(输入)query_buffer的长度。

answer_buffer
(输出)指向存储响应位置的指针。

answer_buffer_length
(输入)answer_buffer的大小。

5.dn_comp 压缩扩展域名字

参数

expanded_domain_name
(输入)指向展开的域名的指针。

compressed_domain_name
(输出)指向压缩域名所在位置的指针 数据处理。

answer_buffer_length
(输入)compressed_domain_name缓冲区的大小。

domain_name_pointers
(输入)指向指向以前压缩域的指针数组的指针 当前邮件中的名称。

last_domain_name

(输入)指向domain_name_pointers 指定的数组末尾的指针。

6.dn_expand 展开域名

参数

message_pointer
(输入)指向 DNS 数据包开头的指针。

end_of_message
(输入)指向 DNS 数据包末尾的指针。

compressed_domain_name
(输入)指向 DNS 中压缩域名的指针 包。

expanded_domain_name
(输出)指向展开的域名的指针。

answer_buffer_length
(输入)expanded_domain_name缓冲区的大小。

解析器配置文件

一般为/etc/resolv.conf,关于resolv.conf的说明请参考手册,man resolv.conf

总结:

解析器按照search搜索列表进行循环的搜索解析,直到解析成功为止;

形成search搜索列表的方式有很多,如果显式设置search,则用search;如果没有显式设置search,如果设置了domain,则用domain作为search搜索列表;如果domain和search都没有设置,则使用gethostname返回的主机名的域名部分作为search搜索列表

/etc/resolv.conf参数:

1. nameserver

解析器使用的名称服务器的ip地址,如下配置:

nameserver 192.168.198.2

可以配置多个,解析器使用该选项的规则是按顺序查询,查询超时,则查询下一个,直到查询最后一个nameserver

如果没有nameserver配置项,解析器使用本地主机上的名称服务器进行解析

2. domain

本地域名设置

(1) 当查询名称时,没有使用FQDN全名称时(后缀点),查询名称时先在名称后面加上domain后查询,如下示例:

设置

domain james.cn

ping apache时,实际上会查询apache.james.cn

ping apache.时,只会查询apache.(因为后缀点)

ping apache.xyz时,先查询apache.xyz,然后查询apache.xyz.james.cn

(2) 当没有设置domain时,会以gethostname函数返回的名称的域名后缀为domain,如下示例:

未设置domain

hostname为:bindforward.james.cn

ping apache时,会查询apache.james.cn

3. search

主机名搜索列表

(1) 当没有定义search时,缺省的search为本地域名domain

(2) 当定义了search时,以search为顺序进行搜索,domain一般将不起作用,示例如下:

domain james.cn search james.com.cn james.cn

ping xyz时,会查询xyz.james.com.cn,然后查询xyz.james.cn(domain项没起做作用)

ping xyz.yy时,会查询xyz.yy,再查询xyz.yy.james.com.cn,然后查询xyz.yy. james.cn

(domain项目仍然没有起作用)

search最多可以定义6个域名搜索项

4. options

选项很多,常用的有timeout、attempts

  • timeout设置超时
  • attempts设置重试次数

如下设置:

options timeout:2 attempts:2

5. nsswitch.conf配置文件

/etc/nsswitch.conf配置文件中的hosts配置项目,如下

hosts: files dns

定义了主机名解析的顺序,先使用hosts文件,再使用dns解析

同样host.conf(/etc/host.conf)也有此功能,如下:

order hosts,bind

定义了解析器解析方法的顺序,先使用hosts文件,再使用bind

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值