diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-26 17:21:13 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-10-26 17:21:13 +0000 |
commit | 670a6626cabc1498f32b35f959591f8621d8447e (patch) | |
tree | 8fb308735a25ded208a2fcbf2561de6f13bf1408 /docs | |
parent | ebe578ab2fc19e9ce0d876a10fc389b018a30eba (diff) | |
download | busybox-w32-670a6626cabc1498f32b35f959591f8621d8447e.tar.gz busybox-w32-670a6626cabc1498f32b35f959591f8621d8447e.tar.bz2 busybox-w32-670a6626cabc1498f32b35f959591f8621d8447e.zip |
add ipv6 developer doc
Diffstat (limited to 'docs')
-rw-r--r-- | docs/ipv4_ipv6.txt | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/docs/ipv4_ipv6.txt b/docs/ipv4_ipv6.txt new file mode 100644 index 000000000..5a63aa776 --- /dev/null +++ b/docs/ipv4_ipv6.txt | |||
@@ -0,0 +1,222 @@ | |||
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 | bzero(&hints, 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 addr, from; | ||
216 | ... | ||
217 | ServSock = socket(AF_INET6, SOCK_STREAM, PF_INET6); | ||
218 | bind(ServSock, &addr, sizeof(addr)); | ||
219 | do { | ||
220 | csock = accept(ServSocket, &from, sizeof(from)); | ||
221 | doClientStuff(csock); | ||
222 | } while (!finished); | ||