- remove functions marked as LEGACY in SUSv3 and use their modern counterparts.
[oweals/busybox.git] / docs / ipv4_ipv6.txt
1 We need better network address conv helpers.
2 This is what our applets want:
3
4           sockaddr -> hostname
5 udhcp:    hostname -> ipv4 addr
6 nslookup: hostname -> list of names - done
7 tftp:     host,port -> sockaddr
8 nc:       host,port -> sockaddr
9 inetd: ?
10 traceroute: ?, hostname -> ipv4 addr
11 arping    hostname -> ipv4 addr
12 ping6     hostname -> ipv6 addr
13 ifconfig  hostname -> ipv4 addr (FIXME error check?)
14 ipcalc    ipv4 addr -> hostname
15 syslogd   hostname -> sockaddr
16 inet_common.c: buggy. hostname -> ipv4 addr
17 mount     hostname -> sockaddr_in
18
19 ==================
20 HOWTO get rid of inet_ntoa/aton:
21
22 foo.sin_addr.s_addr = inet_addr(cp);
23 -
24 inet_pton(AF_INET, cp, &foo.sin_addr);
25
26 inet_aton(cp, &foo.sin_addr);
27 -
28 inet_pton(AF_INET, cp, &foo.sin_addr);
29
30 ptr = inet_ntoa(foo.sin_addr);
31 -
32 char str[INET_ADDRSTRLEN];
33 ptr = inet_ntop(AF_INET, &foo.sin_addr, str, sizeof(str));
34
35 ===================
36
37        struct addrinfo {
38            int     ai_flags;
39            int     ai_family;
40            int     ai_socktype;
41            int     ai_protocol;
42            size_t  ai_addrlen;
43            struct sockaddr *ai_addr;
44            char   *ai_canonname;
45            struct addrinfo *ai_next;
46        };
47        int getaddrinfo(const char *node, const char *service,
48                        const struct addrinfo *hints,
49                        struct addrinfo **res);
50
51        void freeaddrinfo(struct addrinfo *res);
52
53        const char *gai_strerror(int errcode);
54
55        The members ai_family, ai_socktype, and ai_protocol have the same  meaning
56        as  the corresponding parameters in the socket(2) system call.  The getad-
57        drinfo(3) function returns socket addresses in either IPv4 or IPv6 address
58        family, (ai_family will be set to either AF_INET or AF_INET6).
59
60        The  hints  parameter specifies the preferred socket type, or protocol.  A
61        NULL hints specifies that any network address or protocol  is  acceptable.
62        If  this  parameter  is  not NULL it points to an addrinfo structure whose
63        ai_family, ai_socktype, and  ai_protocol  members  specify  the  preferred
64        socket type.  AF_UNSPEC in ai_family specifies any protocol family (either
65        IPv4 or IPv6, for example).  0 in  ai_socktype  or  ai_protocol  specifies
66        that any socket type or protocol is acceptable as well.  The ai_flags mem-
67        ber specifies additional options, defined below.  Multiple flags are spec-
68        ified  by  logically  OR-ing  them together.  All the other members in the
69        hints parameter must contain either 0, or a null pointer.
70
71        The node or service parameter, but not both, may be NULL.  node  specifies
72        either  a  numerical network address (dotted-decimal format for IPv4, hex-
73        adecimal format for IPv6) or a network hostname, whose  network  addresses
74        are looked up and resolved.  If hints.ai_flags contains the AI_NUMERICHOST
75        flag then the node parameter must be a  numerical  network  address.   The
76        AI_NUMERICHOST  flag  suppresses  any  potentially  lengthy  network  host
77        address lookups.
78
79        The getaddrinfo(3) function creates a linked list of addrinfo  structures,
80        one  for  each  network address subject to any restrictions imposed by the
81        hints parameter.  The ai_canonname field of the first  of  these  addrinfo
82        structures  is  set  to  point  to  the  official  name  of  the  host, if
83        hints.ai_flags includes the AI_CANONNAME  flag.   ai_family,  ai_socktype,
84        and  ai_protocol specify the socket creation parameters.  A pointer to the
85        socket address is placed in the ai_addr member,  and  the  length  of  the
86        socket address, in bytes, is placed in the ai_addrlen member.
87
88        If  node is NULL, the network address in each socket structure is initial-
89        ized according to the AI_PASSIVE flag, which  is  set  in  hints.ai_flags.
90        The  network  address in each socket structure will be left unspecified if
91        AI_PASSIVE flag is set.  This is used by server applications, which intend
92        to  accept client connections on any network address.  The network address
93        will be set to the loopback interface address if the  AI_PASSIVE  flag  is
94        not  set.  This is used by client applications, which intend to connect to
95        a server running on the same network host.
96
97        If hints.ai_flags includes the AI_ADDRCONFIG flag, then IPv4 addresses are
98        returned  in the list pointed to by result only if the local system has at
99        least has at least one IPv4 address configured,  and  IPv6  addresses  are
100        only  returned  if  the local system has at least one IPv6 address config-
101        ured.
102
103        If hint.ai_flags specifies the AI_V4MAPPED flag, and  hints.ai_family  was
104        specified as AF_INET6, and no matching IPv6 addresses could be found, then
105        return IPv4-mapped IPv6 addresses in the list pointed to  by  result.   If
106        both  AI_V4MAPPED and AI_ALL are specified in hints.ai_family, then return
107        both IPv6 and IPv4-mapped IPv6 addresses in the list pointed to by result.
108        AI_ALL is ignored if AI_V4MAPPED is not also specified.
109
110        service  sets the port number in the network address of each socket struc-
111        ture.  If service is NULL the port number will be left uninitialized.   If
112        AI_NUMERICSERV  is  specified  in  hints.ai_flags and service is not NULL,
113        then service must point to a string  containing  a  numeric  port  number.
114        This  flag  is used to inhibit the invocation of a name resolution service
115        in cases where it is known not to be required.
116
117
118 ==============
119
120        int getnameinfo(const struct sockaddr *sa, socklen_t salen,
121                        char *host, size_t hostlen,
122                        char *serv, size_t servlen, int flags);
123
124        The  getnameinfo(3)  function is defined for protocol-independent
125        address-to-nodename translation.  It combines the functionality
126        of gethostbyaddr(3) and getservbyport(3) and is the inverse of
127        getaddrinfo(3).  The sa argument is a pointer to a generic socket address
128        structure (of type sockaddr_in or  sockaddr_in6)  of  size  salen  that
129        holds  the  input IP address and port number.  The arguments host and
130        serv are pointers to buffers (of size hostlen and servlen respectively)
131        to hold the return values.
132
133        The caller can specify that no hostname (or no service name) is required
134        by providing a NULL host (or serv) argument or a zero hostlen (or servlen)
135        parameter. However, at least one of hostname or service name must be requested.
136
137        The flags argument modifies the behaviour of getnameinfo(3) as follows:
138
139        NI_NOFQDN
140               If set, return only the hostname part of the FQDN for local hosts.
141
142        NI_NUMERICHOST
143               If set, then the numeric form of the hostname is returned.
144               (When not set, this will still happen in case the node's name
145               cannot be looked up.)
146
147        NI_NAMEREQD
148               If set, then a error is returned if the hostname cannot be looked up.
149
150        NI_NUMERICSERV
151               If set, then the service address is returned in numeric form,
152               for example by its port number.
153
154        NI_DGRAM
155               If  set, then the service is datagram (UDP) based rather than stream
156               (TCP) based. This is required for the few ports (512-514) that have different
157               services for UDP and TCP.
158
159 =================
160
161 Modified IPv6-aware C code:
162
163     struct addrinfo *res, *aip;
164     struct addrinfo hints;
165     int sock = -1;
166     int error;
167
168     /* Get host address. Any type of address will do. */
169     memset(&hints, 0, sizeof(hints));
170     hints.ai_flags = AI_ALL|AI_ADDRCONFIG;
171     hints.ai_socktype = SOCK_STREAM;
172
173     error = getaddrinfo(hostname, servicename, &hints, &res);
174     if (error != 0) {
175        (void) fprintf(stderr,
176           "getaddrinfo: %s for host %s service %s\n",
177           gai_strerror(error), hostname, servicename);
178        return -1;
179     }
180     /* Try all returned addresses until one works */
181     for (aip = res; aip != NULL; aip = aip->ai_next) {
182        /*
183        * Open socket. The address type depends on what
184        * getaddrinfo() gave us.
185        */
186        sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
187        if (sock == -1) {
188           perror("socket");
189           freeaddrinfo(res);
190           return -1;
191        }
192
193        /* Connect to the host. */
194        if (connect(sock, aip->ai_addr, aip->ai_addrlen) == -1) {
195           perror("connect");
196           (void) close(sock);
197           sock = -1;
198           continue;
199        }
200        break;
201     }
202     freeaddrinfo(res);
203
204 Note that for new applications, if you write address-family-agnostic data structures,
205 there is no need for porting.
206
207 However, when it comes to server-side programming in C/C++, there is an additional wrinkle.
208 Namely, depending on whether your application is written for a dual-stack platform, such
209 as Solaris or Linux, or a single-stack platform, such as Windows, you would need to
210 structure the code differently.
211
212 Here's the corresponding server C code for a dual-stack platform:
213
214     int ServSock, csock;
215     /* struct sockaddr is too small! */
216     struct sockaddr_storage addr, from;
217     ...
218     ServSock = socket(AF_INET6, SOCK_STREAM, PF_INET6);
219     bind(ServSock, &addr, sizeof(addr));
220     do {
221        csock = accept(ServSocket, &from, sizeof(from));
222        doClientStuff(csock);
223     } while (!finished);