]>
Commit | Line | Data |
---|---|---|
1fb05e3d UD |
1 | /* The Inner Net License, Version 2.00 |
2 | ||
3 | The author(s) grant permission for redistribution and use in source and | |
4 | binary forms, with or without modification, of the software and documentation | |
5 | provided that the following conditions are met: | |
6 | ||
7 | 0. If you receive a version of the software that is specifically labelled | |
8 | as not being for redistribution (check the version message and/or README), | |
9 | you are not permitted to redistribute that version of the software in any | |
10 | way or form. | |
11 | 1. All terms of the all other applicable copyrights and licenses must be | |
12 | followed. | |
13 | 2. Redistributions of source code must retain the authors' copyright | |
14 | notice(s), this list of conditions, and the following disclaimer. | |
15 | 3. Redistributions in binary form must reproduce the authors' copyright | |
16 | notice(s), this list of conditions, and the following disclaimer in the | |
17 | documentation and/or other materials provided with the distribution. | |
18 | 4. All advertising materials mentioning features or use of this software | |
19 | must display the following acknowledgement with the name(s) of the | |
20 | authors as specified in the copyright notice(s) substituted where | |
21 | indicated: | |
22 | ||
23 | This product includes software developed by <name(s)>, The Inner | |
24 | Net, and other contributors. | |
25 | ||
26 | 5. Neither the name(s) of the author(s) nor the names of its contributors | |
27 | may be used to endorse or promote products derived from this software | |
28 | without specific prior written permission. | |
29 | ||
30 | THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY | |
31 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
32 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
33 | DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY | |
34 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
35 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
36 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
37 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
38 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
39 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
40 | ||
41 | If these license terms cause you a real problem, contact the author. */ | |
42 | ||
43 | /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */ | |
44 | ||
1fb05e3d UD |
45 | #include <sys/types.h> |
46 | #include <sys/socket.h> | |
47 | ||
48 | #include <netinet/in.h> | |
1fb05e3d UD |
49 | #include <sys/un.h> |
50 | #include <sys/utsname.h> | |
1fb05e3d UD |
51 | #include <netdb.h> |
52 | #include <errno.h> | |
53 | #include <string.h> | |
54 | #include <stdio.h> | |
55 | #include <unistd.h> | |
5a97622d | 56 | #include <alloca.h> |
5107cf1d | 57 | #include <bits/libc-lock.h> |
5a97622d | 58 | #include <arpa/inet.h> |
1fb05e3d | 59 | |
1fb05e3d | 60 | #ifndef min |
cd6ede75 | 61 | # define min(x,y) (((x) > (y)) ? (y) : (x)) |
1fb05e3d UD |
62 | #endif /* min */ |
63 | ||
1fb05e3d | 64 | |
40a55d20 | 65 | static char * |
dfd2257a | 66 | internal_function |
cd6ede75 | 67 | nrl_domainname (void) |
1fb05e3d | 68 | { |
390500b1 UD |
69 | static char *domain; |
70 | static int not_first; | |
1fb05e3d | 71 | |
3a07823a | 72 | if (! not_first) |
cd6ede75 UD |
73 | { |
74 | __libc_lock_define_initialized (static, lock); | |
75 | __libc_lock_lock (lock); | |
76 | ||
3a07823a | 77 | if (! not_first) |
cd6ede75 UD |
78 | { |
79 | char *c; | |
80 | struct hostent *h, th; | |
40a55d20 | 81 | size_t tmpbuflen = 1024; |
cd6ede75 UD |
82 | char *tmpbuf = alloca (tmpbuflen); |
83 | int herror; | |
84 | ||
390500b1 | 85 | not_first = 1; |
cd6ede75 UD |
86 | |
87 | while (__gethostbyname_r ("localhost", &th, tmpbuf, tmpbuflen, &h, | |
88 | &herror)) | |
89 | { | |
90 | if (herror == NETDB_INTERNAL && errno == ERANGE) | |
91 | { | |
92 | tmpbuflen *= 2; | |
93 | tmpbuf = alloca (tmpbuflen); | |
94 | } | |
95 | else | |
96 | break; | |
97 | } | |
5a97622d | 98 | |
cd6ede75 UD |
99 | if (h && (c = strchr (h->h_name, '.'))) |
100 | domain = __strdup (++c); | |
101 | else | |
102 | { | |
103 | /* The name contains no domain information. Use the name | |
104 | now to get more information. */ | |
50304ef0 | 105 | while (__gethostname (tmpbuf, tmpbuflen)) |
cd6ede75 UD |
106 | { |
107 | tmpbuflen *= 2; | |
108 | tmpbuf = alloca (tmpbuflen); | |
109 | } | |
5a97622d | 110 | |
cd6ede75 UD |
111 | if ((c = strchr (tmpbuf, '.'))) |
112 | domain = __strdup (++c); | |
113 | else | |
114 | { | |
115 | /* We need to preserve the hostname. */ | |
116 | const char *hstname = strdupa (tmpbuf); | |
117 | ||
118 | while (__gethostbyname_r (hstname, &th, tmpbuf, tmpbuflen, | |
119 | &h, &herror)) | |
120 | { | |
121 | if (herror == NETDB_INTERNAL && errno == ERANGE) | |
122 | { | |
123 | tmpbuflen *= 2; | |
124 | tmpbuf = alloca (tmpbuflen); | |
125 | } | |
126 | else | |
127 | break; | |
128 | } | |
129 | ||
130 | if (h && (c = strchr(h->h_name, '.'))) | |
131 | domain = __strdup (++c); | |
132 | else | |
133 | { | |
134 | struct in_addr in_addr; | |
135 | ||
136 | in_addr.s_addr = htonl (0x7f000001); | |
137 | ||
138 | while (__gethostbyaddr_r ((const char *) &in_addr, | |
139 | sizeof (struct in_addr), | |
140 | AF_INET, &th, tmpbuf, | |
141 | tmpbuflen, &h, &herror)) | |
142 | { | |
143 | if (herror == NETDB_INTERNAL && errno == ERANGE) | |
144 | { | |
145 | tmpbuflen *= 2; | |
146 | tmpbuf = alloca (tmpbuflen); | |
147 | } | |
148 | else | |
149 | break; | |
150 | } | |
151 | ||
152 | if (h && (c = strchr (h->h_name, '.'))) | |
153 | domain = __strdup (++c); | |
154 | } | |
155 | } | |
5a97622d | 156 | } |
5a97622d | 157 | } |
1fb05e3d | 158 | |
cd6ede75 | 159 | __libc_lock_unlock (lock); |
1fb05e3d UD |
160 | } |
161 | ||
1fb05e3d UD |
162 | return domain; |
163 | }; | |
164 | ||
cd6ede75 UD |
165 | |
166 | int | |
c7614ee9 | 167 | getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, |
cd6ede75 | 168 | size_t hostlen, char *serv, size_t servlen, int flags) |
1fb05e3d UD |
169 | { |
170 | int serrno = errno; | |
5a97622d UD |
171 | int tmpbuflen = 1024; |
172 | int herrno; | |
cd6ede75 | 173 | char *tmpbuf = alloca (tmpbuflen); |
5a97622d | 174 | struct hostent th; |
922809a2 | 175 | socklen_t min_addrlen = 0; |
1fb05e3d | 176 | |
922809a2 UD |
177 | if (sa == NULL || addrlen < sizeof (sa_family_t)) |
178 | return -1; | |
179 | ||
180 | switch (sa->sa_family) | |
181 | { | |
182 | case AF_LOCAL: | |
183 | min_addrlen = (socklen_t) (((struct sockaddr_un *) NULL)->sun_path); | |
184 | break; | |
185 | default: | |
186 | min_addrlen = __libc_sa_len (sa->sa_family); | |
187 | } | |
188 | if (addrlen < min_addrlen) | |
1fb05e3d UD |
189 | return -1; |
190 | ||
cd6ede75 UD |
191 | if (host != NULL && hostlen > 0) |
192 | switch(sa->sa_family) | |
193 | { | |
1fb05e3d | 194 | case AF_INET: |
1fb05e3d | 195 | case AF_INET6: |
cd6ede75 UD |
196 | if (!(flags & NI_NUMERICHOST)) |
197 | { | |
198 | struct hostent *h = NULL; | |
cd6ede75 UD |
199 | if (h == NULL) |
200 | { | |
cd6ede75 UD |
201 | if (sa->sa_family == AF_INET6) |
202 | { | |
203 | while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in6 *) sa)->sin6_addr), | |
204 | sizeof(struct in6_addr), | |
205 | AF_INET6, &th, tmpbuf, tmpbuflen, | |
206 | &h, &herrno)) | |
207 | { | |
208 | if (herrno == NETDB_INTERNAL) | |
209 | { | |
210 | if (errno == ERANGE) | |
211 | { | |
212 | tmpbuflen *= 2; | |
213 | tmpbuf = alloca (tmpbuflen); | |
214 | } | |
215 | else | |
216 | { | |
217 | __set_h_errno (herrno); | |
40a55d20 UD |
218 | __set_errno (serrno); |
219 | return -1; | |
cd6ede75 UD |
220 | } |
221 | } | |
222 | else | |
223 | { | |
224 | break; | |
225 | } | |
226 | } | |
5a97622d | 227 | } |
cd6ede75 UD |
228 | else |
229 | { | |
cd6ede75 UD |
230 | while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in *)sa)->sin_addr), |
231 | sizeof(struct in_addr), AF_INET, | |
232 | &th, tmpbuf, tmpbuflen, | |
233 | &h, &herrno)) | |
234 | { | |
235 | if (errno == ERANGE) | |
236 | { | |
237 | tmpbuflen *= 2; | |
238 | tmpbuf = alloca (tmpbuflen); | |
239 | } | |
240 | else | |
241 | { | |
242 | break; | |
243 | } | |
244 | } | |
245 | } | |
5a97622d | 246 | } |
1fb05e3d | 247 | |
cd6ede75 UD |
248 | if (h) |
249 | { | |
250 | if (flags & NI_NOFQDN) | |
251 | { | |
40a55d20 | 252 | char *c; |
cd6ede75 UD |
253 | if ((c = nrl_domainname ()) && (c = strstr(h->h_name, c)) |
254 | && (c != h->h_name) && (*(--c) == '.')) | |
255 | { | |
256 | strncpy (host, h->h_name, | |
257 | min(hostlen, (size_t) (c - h->h_name))); | |
6e9b72d3 UD |
258 | host[min(hostlen - 1, (size_t) (c - h->h_name))] |
259 | = '\0'; | |
cd6ede75 UD |
260 | break; |
261 | } | |
262 | } | |
263 | strncpy (host, h->h_name, hostlen); | |
1fb05e3d | 264 | break; |
cd6ede75 UD |
265 | } |
266 | } | |
1fb05e3d UD |
267 | |
268 | if (flags & NI_NAMEREQD) | |
40a55d20 UD |
269 | { |
270 | __set_errno (serrno); | |
271 | return -1; | |
272 | } | |
cd6ede75 UD |
273 | else |
274 | { | |
275 | const char *c; | |
cd6ede75 UD |
276 | if (sa->sa_family == AF_INET6) |
277 | c = inet_ntop (AF_INET6, | |
278 | (void *) &(((struct sockaddr_in6 *) sa)->sin6_addr), | |
279 | host, hostlen); | |
280 | else | |
cd6ede75 UD |
281 | c = inet_ntop (AF_INET, |
282 | (void *) &(((struct sockaddr_in *) sa)->sin_addr), | |
283 | host, hostlen); | |
1fb05e3d | 284 | |
40a55d20 UD |
285 | if (c == NULL) |
286 | { | |
287 | __set_errno (serrno); | |
288 | return -1; | |
289 | } | |
cd6ede75 | 290 | } |
1fb05e3d | 291 | break; |
cd6ede75 | 292 | |
1fb05e3d | 293 | case AF_LOCAL: |
cd6ede75 UD |
294 | if (!(flags & NI_NUMERICHOST)) |
295 | { | |
296 | struct utsname utsname; | |
1fb05e3d | 297 | |
cd6ede75 UD |
298 | if (!uname (&utsname)) |
299 | { | |
300 | strncpy (host, utsname.nodename, hostlen); | |
301 | break; | |
302 | }; | |
1fb05e3d | 303 | }; |
1fb05e3d UD |
304 | |
305 | if (flags & NI_NAMEREQD) | |
40a55d20 UD |
306 | { |
307 | __set_errno (serrno); | |
308 | return -1; | |
309 | } | |
1fb05e3d | 310 | |
cd6ede75 | 311 | strncpy (host, "localhost", hostlen); |
1fb05e3d | 312 | break; |
cd6ede75 | 313 | |
1fb05e3d UD |
314 | default: |
315 | return -1; | |
cd6ede75 | 316 | } |
1fb05e3d UD |
317 | |
318 | if (serv && (servlen > 0)) | |
cd6ede75 UD |
319 | switch(sa->sa_family) |
320 | { | |
1fb05e3d | 321 | case AF_INET: |
1fb05e3d | 322 | case AF_INET6: |
cd6ede75 UD |
323 | if (!(flags & NI_NUMERICSERV)) |
324 | { | |
325 | struct servent *s, ts; | |
326 | while (__getservbyport_r (((struct sockaddr_in *) sa)->sin_port, | |
327 | ((flags & NI_DGRAM) ? "udp" : "tcp"), | |
328 | &ts, tmpbuf, tmpbuflen, &s)) | |
329 | { | |
330 | if (herrno == NETDB_INTERNAL) | |
331 | { | |
332 | if (errno == ERANGE) | |
333 | { | |
334 | tmpbuflen *= 2; | |
40a55d20 | 335 | tmpbuf = __alloca (tmpbuflen); |
cd6ede75 UD |
336 | } |
337 | else | |
40a55d20 UD |
338 | { |
339 | __set_errno (serrno); | |
340 | return -1; | |
341 | } | |
cd6ede75 UD |
342 | } |
343 | else | |
344 | { | |
345 | break; | |
346 | } | |
347 | } | |
348 | if (s) | |
349 | { | |
40a55d20 | 350 | strncpy (serv, s->s_name, servlen); |
cd6ede75 | 351 | break; |
5a97622d | 352 | } |
5a97622d | 353 | } |
50304ef0 UD |
354 | __snprintf (serv, servlen, "%d", |
355 | ntohs (((struct sockaddr_in *) sa)->sin_port)); | |
1fb05e3d | 356 | break; |
cd6ede75 | 357 | |
1fb05e3d | 358 | case AF_LOCAL: |
cd6ede75 | 359 | strncpy (serv, ((struct sockaddr_un *) sa)->sun_path, servlen); |
1fb05e3d | 360 | break; |
cd6ede75 UD |
361 | } |
362 | ||
1fb05e3d UD |
363 | if (host && (hostlen > 0)) |
364 | host[hostlen-1] = 0; | |
365 | if (serv && (servlen > 0)) | |
366 | serv[servlen-1] = 0; | |
367 | errno = serrno; | |
368 | return 0; | |
40a55d20 | 369 | } |