Learning notes of UNIX Network Programming Volume 1: socket networking API -- name and address conversion

Posted by kparish on Fri, 14 Jan 2022 07:13:58 +0100

Domain name system

Domain name system (DNS) is mainly used for the mapping between host name and IP address.
The host name can be either a simple name, such as solaris or bsdi, or a fully qualified domain name (FQDN), such as solaris unpbook. com .

resource record

Entries in DNS are called resource records (RR s).

  • A. A record maps a host name to a 32-bit IPv4 address.
  • AAAA, an AAAA record called A quad A record, maps A host name to A 128 bit IPv6 address.
  • PTR, a PTR record called "pointer record", maps IP addresses to host names.
  • MX, MX record specifies a host as the "mail exchanger" of a given host.
  • CNAME, CNAME stands for "canonical name". Its common usage is to assign CNAME records to commonly used services (such as ftp and www).

Parser and nameserver

Each organization often runs one or more name servers, which are usually called BIND (short for Berkeley Internet Name Domain) programs.


The parser code determines the location of the name servers of the organization by reading the relevant system configuration files.

File / etc / resolv Conf usually contains the IP address of the local nameserver host.

The parser uses UDP to issue queries to the local name server.

DNS alternative

It is also possible to obtain name and address information without using DNS.

Common alternatives are static host files (usually / etc/hosts files), network information system (NIS), and Lightweight Directory Access Protocol (LDAP).

gethostbyname function

#include <netdb.h>
struct hostent *gethostbyname(const char*hostname);
                                   Return: non null pointer if successful; null pointer if error NULL And set h_errno
struct hostent
{
	char *h_name;// host name
	char **h_aliases;// Alias list
	int h_addrtype;
	int h_length;// Number of IP addresses
	char **h_addr_list;// IP address list
};


When an error occurs, it does not set the errno variable, but sets the global integer variable h_errno is set in the header file < netdb h> One of the following constant values defined in:

  • HOST_NOT_FOUND;
  • TRY_AGAIN;
  • NO_RECOVERY;
  • NO_DATA (equivalent to NO_ADDRESS).

NO_ A data error indicates that the specified name is valid.

gethostbyaddr function

#include <netdb.h>
struct hostent *gethostbyaddr(const char *addr, sock_len_t len, int family);
                                Return: non null pointer if successful; null pointer if error NULL And set h_errno 

The gethostbyaddr function attempts to find the corresponding host name from a binary IP address, which is just the opposite of gethostbyname.

getservbyname and getservbyport functions

Service: provide a function
Protocol: provide services in the form of TCP or UDP
The service shall be based on a transport protocol and provided at a specified port

Service configuration file: / etc/services
However, even if some services are configured in this configuration file, the actual host may not be enabled
Some services actually work, but they are not configured under this configuration file
The configuration in this configuration file cannot be guaranteed to be consistent with the actual situation
Therefore, it can only provide a reference value

#include <netdb.h>
struct servent* getservbyname(
	const char* servname, // service name
	const char* protoname);// Agreement for services
                            
                            Return: non null pointer if successful; null pointer if error NULL

The non null pointer returned by this function points to the following serve structure.

struct servent
{
	char *s_name;// service name
	char **s_aliases;// Alias list
	int s_port;// Service port number, expressed in network byte order. It can be used directly later
	char *s_proto;// Agreement for services
};

The function getservbyport is used to find the corresponding service according to the given port number and optional protocol.

#include <netdb.h>
struct servent *getservbyport(
	int port,// Service port number. It needs to pass the parameter of network byte order. htons can be used
	const char *protoname);// Agreement for services

                              Return: non null pointer if successful; null pointer if error NULL

getaddrinfo function

#include <netdb.h>
int getaddrinfo(
	// Host name / IPv4,Ipv6 address in dotted form
	const char *hostname,
	// Service name / service port number
	const char *service,
	// Can be NULL
	// Used to fill in the hint of the expected return information type
	const struct addrinfo *hints,
	struct addrinfo **result);

                                  Return: 0 if successful, non-0 if error
struct addrinfo
{
	int ai_flags;
	int ai_family;
	int ai_socktype;
	int ai_protocol;
	char* ai_canonname;
	socklen_t ai_addrlen;
	struct sockaddr *ai_addr;
	struct addrinfo *ai_next;
};

The members that the caller can set in the hints structure are:

  • ai_flags (zero or more or together AI_xxx);
  • ai_family (an AF_xxx value);
  • ai_socktype (a SOCK_xxx value);
  • ai_protocol .

Where AI_ Flag values available to flag members and their meanings are as follows:

  • AI_PASSIVE sockets are used for passive opening
  • AI_CANONNAME returns the canonical name of the host
  • AI_NUMERICHOST hostname must be an address string
  • AI_NUMERICSERV service needs to be a decimal port number string
  • AI_V4MAPPED requires to return IPV6, but if there is no IPV6 address, it is also allowed to return IPV4 address [which will be mapped to IPV6 address]
  • AI_ALL
  • AI_ADDRCONFIG

When the server process uses getaddrinfo, it generally only specifies service and AI in hints_ Passive. In this way, the IP part of the returned struct sockaddr structure is similar to inaddr_ ANY[IPV4]/IN6ADDR_ ANY_ As init achieved.

When the client process uses getaddrinfo for socket creation and local binding purposes, the host name is not set, and the hints do not contain AI_ Pass. The IP part of the returned struct sockaddr structure is similar to that obtained by 0:: 1 / 127.0.0.1.

struct sockaddr_storage is a socket address structure, which can accommodate various types of address objects such as IPV4/IPV6 / domain sockets, and meet their alignment restrictions.

gai_strerror function

#include <netdb.h>
const char *gai_strerror(int error);
                                     Return: pointer to error description message string

freeaddrinfo function

All storage spaces returned by getaddrinfo are obtained dynamically (for example, from malloc calls), including addrindo structure and ai_addr structure and ai_canonname string.

These storage spaces are returned to the system by calling freeaddrinfo.

#include <netdb.h>
void freeaddrinfo(struct addrinfo *ai);

The ai parameter should point to the first addrinfo structure returned by getaddrinfo.
All structures in the linked list and any dynamic storage space pointed to by them (such as socket address structure and canonical host name) are released.

getaddrinfo function: IPv6

getnameinfo function

The complementary functions of getnameinfo and getaddrinfo take a socket address as a parameter and return a string describing the host and another string describing the service.

#include <netdb.h>
int getnameinfo(
	// Points to a socket address structure
	const struct sockaddr* sockaddr,
	socklen_t addrlen,
	char *host,
	socklen_t hostlen,
	char *serv,
	socklen_t servlen,
	int flags);

                                   Return: 0 if successful, non-0 if error

Learning References:

<UNIX Network Programming Volume 1: socket networking API> 3rd Edition

Topics: Unix network server