Contents of /trunk/mkinitrd-magellan/busybox/docs/ipv4_ipv6.txt
Parent Directory
|
Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 9552 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 9552 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
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); |