The working principle of DDNS and its realization on Linux _linux

Source: Internet
Author: User
Tags function prototype int size socket

Analysis of the working principle of DDNS
DDNS implementation of the most fundamental point is that when the host IP address changes, the implementation of DNS mapping information in a timely manner, the application needs to obtain this information in a timely manner, the main methods can be divided into two major categories:

A class is polling mechanism, namely: the application every time, to query the host's current IP address, and compared with the previous, so as to determine whether the network address has changed. Obviously, this method is not only inefficient, but it is difficult to get a compromise value for each time the IP address is queried.
The second type of approach is asynchronous implementation, that is, the application can be notified in a timely manner whenever the IP address of the host changes. This is indeed a simple and efficient approach, but at the same time, another problem arises, that is: the source of the notification should be who to bear it? Obviously, this is a user-space application that is not competent. So we thought of getting the kernel to act as the source of the message. In this way, there is a need for communication between kernel space and user space through messages.
There are many kinds of information interaction between user space and kernel space under Linux, such as: soft interrupt, System call, NetLink and so on. The introduction of these modes of communication and their respective pros and cons are not covered in this article, and you can view the reference resources for yourself.

In many of these modes of communication, NetLink has become the main mode of interaction between the kernel and more and more applications by virtue of its standard socket API, modular implementation, asynchronous communication mechanism, multicast mechanism and so on. In the Linux kernel, we have encapsulated the function of using NetLink to notify the change of the state of a particular network, which is the famous Rtnetlink. For more information about NetLink's implementation in kernel space and the introduction of its API parameters, you can view the reference resources yourself, this article does not make too much detail here.
This article focuses on the specific application of DDNS, demonstrating the entire process of an application that Rtnetlink detects changes in IP addresses and informs user space, as well as applications that use NetLink sockets to receive messages and tell the DNS server how to implement them.

A brief introduction to DDNS work flow
Combined with the above analysis of the working principle of DDNS, we can simply use the DDNS workflow diagram to express:
Figure 1. DDNS's Work Flow chart

As you can see in Figure 1, there are three main parts of the DDNS workflow:

The application is aware that the IP address has changed in real time, as described above, the use of NetLink asynchronous notification mechanism allows applications to get the kernel space in time for these events "notification" can be divided into the following 5 steps:

1, kernel space initialization rtnetlink module, create netlink_route protocol cluster type NetLink socket;
2, the user space creates the Netlink_route protocol cluster type NetLink socket, and binds to the RTMGRP_IPV4_IFADDR multicast group;
3, the user space receives from the kernel space sends the message, if does not have the message, then blocks itself;
4, when the host is assigned a new IPV4 address, kernel space through the netlink_broadcast, the RTM_NEWADDR message sent to the RTNLGRP_IPV4_IFADDR multicast group;
5, the user space receives the message, carries on the verification, the processing;

After the application receives the notification, it sends the DNS update information to the DNS server, in order to notify the DNS server of the updated IP address in a timely manner so that the host on the network can still access itself through the original domain name, common practice is to use open source software nsupdate to send DNS Update information to the DNS server to implement dynamic updates of DNS information.
Finally, corresponding to the first part of the NetLink socket creation, user space and kernel space close the created NetLink socket.

Each of these links and their implementation is described in detail below.

Realization and analysis of IP address change in kernel space rtnetlink detection
Before we start using NetLink sockets and implementing applications that communicate with the kernel, let's analyze how the Rtnetlink modules of the kernel space work.
Initialization of kernel space Rtnetlink
Listing 1. Initialization of Rtnetlink

 /* The following code is from the 
Linux kernel 2.6.18, net/core/rtnetlink.c file,
and only the most important parts related to this topic are selected, others are skipped with ellipses, and then the list is the same.
 * 
 /void __init rtnetlink_init (void) 
 { 
 ... 	
 RTNL = Netlink_kernel_create (Netlink_route, Rtnlgrp_max, RTNETLINK_RCV, this_module); 
 if (RTNL = NULL) 
	 Panic ("Rtnetlink_init:cannot initialize rtnetlink\n"); 
 ...... 

 }

As you can see in Listing 1:
When Rtnetlink is initialized, Netlink_kernel_create is first invoked to create a netlink_route type of netlink socket and to specify the receive function as RTNETLINK_RCV, about Rtnetlink The _RCV implementation details can be consulted on kernel net/core/rtnetlink.c files. It should be noted here that NetLink provides a variety of protocol clusters including Netlink_route, Netlink_firewall, NETLINK_INET_DIAG, etc. (detailed list and the meaning of each protocol cluster can view the reference resources themselves), The Netlink_route type provides a message that the network address has changed, which is exactly what DDNS needs to use.
notification process for kernel space IP address change events
Host IP address changes caused by a number of reasons, such as: DHCP-assigned IP expiration, user manually modified IP, and so on. Whatever the reason, the kernel space will eventually trigger a notification mechanism for the corresponding event, as an example of the most commonly used tool for modifying IPV4 addresses ifconfig.
Ifconfig first create a af_inet socket, and then through the system call IOCTL to complete the configuration, ioctl in the kernel of the corresponding function is Sys_ioctl, for the IP address, subnet mask, default gateway configuration changes, it will eventually call Devinet _ioctl. The DEVINET_IOCTL function handles a variety of commands, including get and set, and DDNS applications are set class commands, Figure 2 gives the ifconfig call tree for the SIOCSIFADDR command (setting up the network address):
Figure 2. Ifconfig Call Tree for siocsifaddr command

As you can see in Figure 2, when the user uses Ifconfig to modify the host's IP address, the kernel calls Rtmsg_ifa after the new address is set, and the event passed is rtm_newaddr.
Listing 2. Rtmsg_ifa Send IP address change message

 * * The following code is excerpted from the Linux kernel 2.6.18, net/ipv4/devinet.c file/static void Rtmsg_ifa (int eve 
	 NT, struct in_ifaddr* IFA) {int size = nlmsg_space (sizeof (struct ifaddrmsg) + 128); 

	 struct Sk_buff *SKB = alloc_skb (size, gfp_kernel); 
 if (!SKB) netlink_set_err (rtnl, 0, rtnlgrp_ipv4_ifaddr, ENOBUFS); 
		 else if (inet_fill_ifaddr (SKB, IFA, 0, 0, event, 0) < 0) {KFREE_SKB (SKB); 
	 Netlink_set_err (RTNL, 0, rtnlgrp_ipv4_ifaddr, einval); 
	 else {netlink_broadcast (rtnl, SKB, 0, rtnlgrp_ipv4_ifaddr, Gfp_kernel); } 
 }

As you can see in Listing 2, the implementation of Rtmsg_ifa mainly includes:
first allocates a space of type struct sk_buff for storing the message content that needs to be sent.
Subsequently, the call INET_FILL_IFADDR fills the message into the cache above (for the format of the message, you can view the reference resources yourself). Notably, RTM_NEWADDR is encapsulated as Nlmsg_type into the NetLink header nlmsghdr that the kernel sends to the application, so that user-space applications can handle different types of messages, depending on type, when they are received. The final of the
Rtmsg_ifa is to invoke Netlink_broadcast to broadcast the encapsulated Sk_buff structure to the RTNLGRP_IPV4_IFADDR group, the following is the kernel space multicast group and the User space multicast group The corresponding relationship of
listing 3. The corresponding relationship between kernel space multicast group and user space multicast group

/* 
The following code is from Linux kernel 2.6.18, include/linux/rtnetlink.h file
 * * 
 rtnetlink multicast 
 groups/enum rtnetlink_groups { 
	 rtnlgrp_none, 
 #define Rtnlgrp_none 		 rtnlgrp_none 
 rtnlgrp_link, 
 #define Rtnlgrp_link 		 rtnlgrp_link ... 
	 RTNLGRP_IPV4_IFADDR, 
 #define RTNLGRP_IPV4_IFADDR 	 rtnlgrp_ipv4_ifaddr ... 
 }; 

 #ifndef __kernel__/ 
 * Rtnetlink multicast groups-backwards compatibility for userspace */ 
 #define Rtmgrp_link 		 1 
 #define RTMGRP_NOTIFY 		 2 
 ... #define RTMGRP_IPV4_IFADDR 	 0x10 ... 
 #endif

To sum up, when the IP address of the host changes, the kernel sends RTM_NEWADDR messages to all RTNLGRP_IPV4_IFADDR multicast members. Therefore, when creating a NetLink socket in user space, you only need to join the RTMGRP_IPV4_IFADDR group, you can realize that when the native IP address is updated, the DDNS application can asynchronously receive the notification message from the kernel space.

User space NetLink socket creation, binding and message receiving processing
User space Create NetLink sockets
The NetLink socket-related operation of user space is exactly the same as the standard socket API, so it can be used like a standard socket for IP protocol communication between two hosts, which is an important reason why NetLink can be used more and more widely.
Listing 4. User space Create NetLink socket

#include <sys/socket.h> 
 #include <linux/types.h> 
 #include <linux/netlink.h> 
 # Include <linux/rtnetlink.h> ... 
 int main (void) 
 { 
 ... 
 .. if ((Nl_socket = socket (Pf_netlink, SOCK_DGRAM, Netlink_route) ==-1) 
   //Specify the communication domain, communication mode, and communication protocol
 exit (1); 
 ...... 
 }

When creating a NetLink socket:
We have specified the communication domain as Pf_netlink, which indicates that this is a netlink socket. Its definition can be found in the kernel include/linux/socket.h file shown below. From this we can also see the af_inet that we are very familiar with:
Listing 5, the macro definition used in Listing 4

 /* The following code is from Include/linux/socket.h file///// 
 supported address families. * * * 
 #define AF_UNSPEC 	   0 
 #define Af_ Unix 		 1/ 	 * UNIX domain sockets/ 
 #define Af_local 		 1/ 	 POSIX name for 	 Af_unix 
 /* Define Af_inet 		 2/ 	 * Internet IP 	 Protocol 
 /* ... #define Af_netlink 		 ... 
 /* Protocol families, same as address families. * * 
 #define Pf_netlink 	 af_netlink 
 ...

For the way of communication, we chose the sock_dgram. In fact, it is possible to use Sock_dgram or Sock_raw for NetLink sockets based on connectionless connections.
For communication protocols, we use the Netlink_route. This is because in Listing 1, kernel space creates a netlink socket and uses it to send a message that changes the IP address, so there needs to be consistency to communicate between the two sides.
user space bound NetLink sockets
Similar to standard socket usage, it is necessary to bind to a NetLink address to be able to send and receive messages after the NetLink socket is established. NetLink addresses are defined in the struct SOCKADDR_NL structure, and the meaning of each structure member can be seen in Appendix 3.
listing 6. User space bind NetLink socket

 #include <sys/socket.h> #include <linux/types.h> #include <linux/netl ink.h> #include <linux/rtnetlink.h> ... int main (void) {... struct SOCKADDR_NL addr//In INCLU 
 As defined in De/linux/netlink.h, the meaning of each member of the structure can be seen in Appendix 3 memset (&ADDR, 0, sizeof (addr));   addr.nl_family = Pf_netlink;       Define the protocol cluster as Pf_netlink addr.nl_groups = rtmgrp_ipv4_ifaddr//join to RTMGRP_IPV4_IFADDR multicast group addr.nl_pid = 0; Let kernel to assign PID ...//Bind the NetLink socket created in Listing 5 to the above protocol address if (bind Nl_socket, (struct sockaddr *) &addr, si 
  Zeof (addr)) = = = 1) {close (nl_socket); 
 Exit (1); 
} 
 ...... 
 }

As you can see from listing 6, when binding an application's NetLink socket, we add ourselves to the RTMGRP_IPV4_IFADDR multicast group, which is consistent with our analysis of the notification process for kernel space IP address change events.
user space receives and processes kernel space messages
similar to standard socket usage, user space receives NetLink messages from kernel space that can be used with recv, recvfrom, or recvmsg. It is worth mentioning that the netlink socket has its own message header: NLMSGHDR structure (the structure of the specific member variables to see the reference resources), and the Nlmsg_type is exactly what we need to use the message type of the field.
listing 7. User space receives kernel space message

#define Max_msg_size 1024 ... #include <sys/socket.h> #include <linux/types.h> #include <linux/    netlink.h> #include <linux/rtnetlink.h> ... struct if_info {int index; Interface serial number char Name[ifnamsiz]; 
 The name of the interface, the Linux kernel include/linux/if.h defines the ifnamsiz uint8_t Mac[eth_alen]; Interface's MAC address, the Linux kernel include/linux/if_ether.h defines eth_alen ...//interface other information struct if_info T 
 Pointer to the next IF_INFO structure; static struct If_info *if_list = NULL; Holds the existing interface list and updates the int receive_netlink_message (struct NLMSGHDR *nl) each time the program is initialized; Functions for receiving messages from kernel space handle_newaddr (struct ifinfomsg *ifi, int len); 
 Used to process functions that send updates to the DNS server ... int main (void) {... int len = 0; struct NLMSGHDR *nl; The struct definition can refer to the kernel include/linux/netlink.h file while (len = Receive_netlink_message (&nl)) > 0) {while NLMSG_OK (n L, Len)//NLMSG related macro definitions can refer to the kernel include/linux/netlink.h file {switch (nl->nlmsg_type{Case RTM_NEWADDR://handling RTM_NEWADDR NetLink Message type//IFINFOMSG structure can refer to kernel include/linux/rtnetlink.h file hand 
			 Le_newaddr ((struct ifinfomsg *) Nlmsg_data (NL), nlmsg_payload (NL, sizeof (struct))); 
			
		 Break ...//handling other NetLink message types, such as: Rtm_newlink, here Skip default:printf ("Unknown netlink messages Type:%d", NL-&GT;NLM 
		 Sg_type); 
	 NL = Nlmsg_next (NL, Len); 
 } if (nl!= NULL) free (NL);
			
 } 
 ...... 
} int receive_netlink_message (struct nlmsghdr **nl) {struct Iovec Iov;///use Iovec to receive struct MSGHDR msg = {NULL, 0 , &iov, 1, NULL, 0, 0}; 
	
 Initializes msghdr int length; 
 *NL = NULL; 

 if ((*nl = (struct NLMSGHDR *) malloc (max_msg_size)) = = NULL) return 0;    Iov.iov_base = *NL; Encapsulation Nlmsghdr Iov.iov_len = max_msg_size; 
	
	 Specifies length = Recvmsg (Nl_socket, &msg, 0); 
	
	 if (length <= 0) free (*NL); 
 return length; }

An application needs to be processed based on changes in IP after it receives a RTM_NEWADDR type of NetLink message. Here the HANDLE_NEWADDR function is used, and the change of IP is divided into two situations: one is that the interface already exists, only the IP has changed, and the other is that interface is newly added. In either case, the HANDLE_NEWADDR function needs to invoke the Update_dns.sh script to notify the DNS server after it has been processed accordingly. About the implementation of update_dns.sh see the next chapter.
listing 8. User space processing kernel space messages

 void handle_newaddr (struct ifinfomsg *ifinfo, int len) {struct if_info; 
			 for (i = if_list i = i->next)//Traversal in_list, find the IP changed interface if (I->index = Ifinfo->ifi_index) 
	
	 Break 
		 if (i!= NULL) {//found the corresponding interface, execute update_dns.sh system (UPDATE_DNS.SH); 
	 Return //No corresponding interface is found, stating that the interface is a newly added if ((i = calloc (sizeof (struct if_info), 1) = = NULL)//Assign a IF_INFO structure for adding 
	
	 The new interface exit (1); According to Ifinfo->ifi_index and other information update if_info structure I, taking into account with the DDNS application is not limited to space, here skip ... system (update_dns.sh); Execute update_dns.sh i->next = if_list; 
 Add the newly discovered interface if_list at the end of the if_list = i; }

An application's interaction with a DNS server
The application can use the Open Source Tool nsupdate to send DNS update messages to the DNS server. The detailed usage and features of nsupdate can be viewed in terms of space, and this chapter will give a brief introduction to the basic usage of the tool.
Nsupdate can read commands from a terminal or file, one line per command. A blank line or a "send" command, the previously entered command is sent to the DNS server, typically using the method shown in Listing 9. Nsupdate default from File/etc/resolv.conf DNS server and domain name, in practical application, we can first parse network parameters, generate nsupdate input file, the last call nsupdate. The update_dns.sh implementation process is shown in Figure 3.
Listing 9. Examples of the use of Nsupdate

 # nsupdate 
 > Server 9.0.148.50  //dns servers address 9.0.148.50, default port 
 > update Delete oldhost.example.com />//Delete Domain oldhost.example.com any A-type records 
 > Update add newhost.example.com 86400 a 172.16.1.1 
 //Add a 172.16.1.1 <----->newhost.example.com A type of record,
 //Record TTL is 24 hours (86,400 seconds)           
 > Send   //Send command

Figure 3. The implementation process of update_dns.sh

NetLink socket shutdown
User space Close NetLink socket
Like the standard socket API, user space closes the NetLink socket using the close function, and the usage is exactly the same. You can refer to the use of the close function in Listing 6 in the DDNS application.
kernel space Close NetLink socket
Kernel space shut down netlink socket using the Sock_release function, the function prototype is as follows:
listing 10. Kernel Empty between closing NetLink socket-sock_release

 
/* The following code is from Linux kernel 3.4.3, net/socket.c file 
 /void sock_release (struct socket * sock);

Where sock is the netlink socket created for netlink_kernel_create.
It is worth mentioning that the Netlink_kernel_release interface is also available in the latest Linux kernel, and the function prototype looks like this:
listing 11. Kernel Space shutdown NetLink socket--netlink_kernel_release

  
/* The following code is from Linux kernel 3.4.3, net/netlink/af_netlink.c file 
 /void Netlink_kernel_release (struct sock * SK);

Where SK creates the NetLink socket for netlink_kernel_create.

Extended revelation of DDNS application implementation
DDNS uses rtnetlink netlink_route protocol cluster sockets to monitor Linux kernel network event "rtm_newaddr" to update DNS mappings in real time Information, which enables dynamic updates of DNS information. In addition to netlink_route,netlink_family also provides a variety of protocol clusters to implement a variety of information reports, such as SELinux, firewalls, netfilter, IPV6 and so on. As far as the Netlink_route protocol cluster is concerned, it also provides multiple multicast group events that correspond to a variety of network connections, network parameters, routing information, network traffic categories, and so on.
This is a revelation that we can use NetLink, especially Rtnetlink, to implement many other network-related applications. For example, if the application needs to monitor the change of the native routing table in real time, it can add itself to the Rtmgrp_ipv4_route and rtmgrp_notify in the user space to create the netlink socket of the Netlink_route protocol cluster. Multicast group (ie: addr.nl_groups = Rtmgrp_ipv4_route | Rtmgrp_notify in this way, a variety of existing routing protocols, including OSPF, RIPv2, BGP and so on, can be implemented; For example: You can also use Rtnetlink to monitor the connection of the network, Rtnetlink in the initialization will Rtnetlink Message processing function rtnetlink_event hanging to the notification chain Netdev_chain, network device startup, shutdown, renaming and other events can trigger the notification chain and callback message processing functions, so as to multicast rtm_newlink or rtm_dellink information, Notifies the user program of the connection to the network.

Summarize
Based on the working principle of DDNS, this paper expounds the implementation flow of DDNS, and on this basis, further demonstrates the interaction between kernel space and user Space Network state IP address change information by using Linux rtnetlink socket, and realizes DDNS customer by using nsupdate User-side and server-side synchronization update, and in the actual application of the full implementation of the DDNS function, hope to be able to use DDNS network management personnel and Linux network programming enthusiasts to provide a useful reference.

Resources

Learn

    • Refer to the way in which user space and kernel spatial data are exchanged under Linux, part 1th: Kernel startup parameters, module parameters and Sysfs, Sysctl, System calls, and NetLink, to understand the various data interchange modes of Linux user space and kernel space, as well as their respective advantages and disadvantages.
    • Refer to "Linux kernel space and user space communication implementation and analysis" to understand the netlink socket in the kernel space API
    • Refer to the Man Manual for NetLink (7) to learn about the various message types, message header formats, message address formats, and their usage, including Netlink_route, which are supported by Linux NetLink.
    • Refer to Nsupdate's Man handbook for detailed usage and features of open Source Tool nsupdate
    • Look for more references in the DeveloperWorks Linux area for Linux developers, including beginners of Linux.

Author: Wang Hanzhi, software engineer, IBM
Bob, software engineer, IBM

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.