加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

DDNS 的工作原理及其在 Linux 上的实现--转

发布时间:2021-01-23 23:29:57 所属栏目:Linux 来源:网络整理
导读:http://www.ibm.com/developerworks/cn/linux/1305_wanghz_ddns/index.html DDNS (Dynamic DNS) 扩展了 DNS 将客户端 IP 与其域名进行静态映射的功能,它可以将同一域名实时地解析为不同的动态 IP,而不需要额外的人工干预。这在客户端 IP 地址不断发生变化

从清单 6 中可以看到,在绑定应用程序的 netlink 套接字时,我们将自己加入到了 RTMGRP_IPV4_IFADDR 组播 group 中,这与前文我们对内核空间 IP 地址变化事件的通知过程的分析是一致的。

同样与标准的 socket 使用方法类似,用户空间接收内核空间发来的 netlink 消息可以使用 recv、recvfrom 或 recvmsg。值得一提的是,netlink 套接字有自己的消息头:nlmsghdr 结构(该结构具体各成员变量的含义请查看),而其中的 nlmsg_type 正是我们需要用到的包含了消息类型的字段。

#include #include #include ...... struct if_info { int index; //interface 的序号 char name[IFNAMSIZ]; //interface 的名称,Linux 内核 include/linux/if.h 中定义了 IFNAMSIZ uint8_t mac[ETH_ALEN]; //interface 的 mac 地址,Linux 内核 include/linux/if_ether.h 中定义了 ETH_ALEN ...... //interface 的其他信息 struct if_info *next; // 指向下一个 if_info 结构的指针 }; static struct if_info *if_list = NULL; // 存放现有的 interface 列表,在每次程序初始化时更新 int receive_netlink_message(struct nlmsghdr *nl); // 用于接收内核空间发来的消息的函数 handle_newaddr(struct ifinfomsg *ifi,int len); // 用于处理向 DNS 服务器发送更新的函数 ...... int main(void) { ...... int len = 0; struct nlmsghdr *nl; // 结构体定义可以参考内核 include/linux/netlink.h 文件

while((len = receive_netlink_message(&nl)) > 0)
{
while(NLMSG_OK(nl,len)) //NLMSG 相关的宏定义可以参考内核 include/linux/netlink.h 文件
{
switch(nl->nlmsg_type)
{
case RTM_NEWADDR: // 处理 RTM_NEWADDR 的 netlink 消息类型
//ifinfomsg 结构可以参考内核 include/linux/rtnetlink.h 文件
handle_newaddr((struct ifinfomsg *)NLMSG_DATA(nl),NLMSG_PAYLOAD(nl,sizeof(struct ifinfomsg)));
break;

     ...... // 处理其他 netlink 消息类型,如:RTM_NEWLINK,这里略过

     default: 
         printf("Unknown netlink message type : %d",nl->nlmsg_type); 
     } 

     nl = NLMSG_NEXT(nl,len); 
 } 
 if( nl != NULL ) 

free(nl);
}
......
}

int receive_netlink_message(struct nlmsghdr **nl)
{
struct iovec iov; // 使用 iovec 进行接收
struct msghdr msg = {NULL,&iov,1,NULL,0}; // 初始化 msghdr
int length;

nl = NULL;
if ((
nl = (struct nlmsghdr *) malloc(MAX_MSG_SIZE)) == NULL )
return 0;

iov.iov_base = *nl; // 封装 nlmsghdr
iov.iov_len = MAX_MSG_SIZE; // 指定长度

 length = recvmsg(nl_socket,&msg,0); 

 if(length <= 0) 

FREE(*nl);

 return length; 

}

应用程序在收到了 RTM_NEWADDR 类型的 netlink 消息后,需要根据 IP 的变化进行处理。这里使用了 handle_newaddr 函数,对 IP 的变化分为了两种情况:一种是 interface 已经存在、仅仅是 IP 发生了变化;另一种是 interface 是新添加的。无论是哪种情况,handle_newaddr 函数在进行了相应的处理之后,都需要调用 update_dns.sh 这个脚本通知 DNS 服务器。关于 update_dns.sh 的实现参见下一章。

for(i = if_list ; i ; i = i->next) // 遍历 in_list,找到 ip 发生变化的 interface if(i->index == ifinfo->ifi_index) break; if(i != NULL){ // 找到了相应的 interface,执行 update_dns.sh system(update_dns.sh); return; }

// 没有找到对应的 interface,说明该 interface 是新添加的
if((i = calloc(sizeof(struct if_info),1)) == NULL)// 分配一个 if_info 结构用于添加新的 interface
exit(1);

 // 根据 ifinfo->ifi_index 等信息更新 if_info 结构 i,考虑到与 ddns 应用关系不大,限于篇幅,这里略过
 ...... 

 system(update_dns.sh); // 执行 update_dns.sh 

 i->next = if_list; // 在 if_list 的末尾添加新发现的 interface 
 if_list = i; 

}

应用程序可以利用开源工具 nsupdate 来向 DNS 服务器发送 DNS update 消息。nsupdate 的详细用法及特性可以请查看,受篇幅所限,本章将会结合例子简单介绍这个工具的基本用法。

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读