Unify names of used global functions.
[kopensolaris-gnu/glibc.git] / inet / getnameinfo.c
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
45 #include <sys/types.h>
46 #include <sys/socket.h>
47
48 #include <netinet/in.h>
49 #include <sys/un.h>
50 #include <sys/utsname.h>
51 #include <netdb.h>
52 #include <errno.h>
53 #include <string.h>
54 #include <stdio.h>
55 #include <unistd.h>
56 #include <alloca.h>
57 #include <bits/libc-lock.h>
58 #include <arpa/inet.h>
59
60 #ifndef min
61 # define min(x,y) (((x) > (y)) ? (y) : (x))
62 #endif /* min */
63
64
65 static char *
66 internal_function
67 nrl_domainname (void)
68 {
69   static char *domain = NULL;
70   static int first = 1;
71
72   if (first)
73     {
74       __libc_lock_define_initialized (static, lock);
75       __libc_lock_lock (lock);
76
77       if (first)
78         {
79           char *c;
80           struct hostent *h, th;
81           size_t tmpbuflen = 1024;
82           char *tmpbuf = alloca (tmpbuflen);
83           int herror;
84
85           first = 0;
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             }
98
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.  */
105               while (__gethostname (tmpbuf, tmpbuflen))
106                 {
107                   tmpbuflen *= 2;
108                   tmpbuf = alloca (tmpbuflen);
109                 }
110
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                 }
156             }
157         }
158
159       __libc_lock_unlock (lock);
160     }
161
162   return domain;
163 };
164
165
166 int
167 getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
168              size_t hostlen, char *serv, size_t servlen, int flags)
169 {
170   int serrno = errno;
171   int tmpbuflen = 1024;
172   int herrno;
173   char *tmpbuf = alloca (tmpbuflen);
174   struct hostent th;
175
176   if (sa == NULL)
177     return -1;
178
179   if (host != NULL && hostlen > 0)
180     switch(sa->sa_family)
181       {
182       case AF_INET:
183       case AF_INET6:
184         if (!(flags & NI_NUMERICHOST))
185           {
186             struct hostent *h = NULL;
187             if (h == NULL)
188               {
189                 if (sa->sa_family == AF_INET6)
190                   {
191                     while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in6 *) sa)->sin6_addr),
192                                               sizeof(struct in6_addr),
193                                               AF_INET6, &th, tmpbuf, tmpbuflen,
194                                               &h, &herrno))
195                       {
196                         if (herrno == NETDB_INTERNAL)
197                           {
198                             if (errno == ERANGE)
199                               {
200                                 tmpbuflen *= 2;
201                                 tmpbuf = alloca (tmpbuflen);
202                               }
203                             else
204                               {
205                                 __set_h_errno (herrno);
206                                 __set_errno (serrno);
207                                 return -1;
208                               }
209                           }
210                         else
211                           {
212                             break;
213                           }
214                       }
215                   }
216                 else
217                   {
218                     while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in *)sa)->sin_addr),
219                                               sizeof(struct in_addr), AF_INET,
220                                               &th, tmpbuf, tmpbuflen,
221                                               &h, &herrno))
222                       {
223                         if (errno == ERANGE)
224                           {
225                             tmpbuflen *= 2;
226                             tmpbuf = alloca (tmpbuflen);
227                           }
228                         else
229                           {
230                             break;
231                           }
232                       }
233                   }
234               }
235
236             if (h)
237               {
238                 if (flags & NI_NOFQDN)
239                   {
240                     char *c;
241                     if ((c = nrl_domainname ()) && (c = strstr(h->h_name, c))
242                         && (c != h->h_name) && (*(--c) == '.'))
243                       {
244                         strncpy (host, h->h_name,
245                                  min(hostlen, (size_t) (c - h->h_name)));
246                         break;
247                       }
248                   }
249                 strncpy (host, h->h_name, hostlen);
250                 break;
251               }
252           }
253
254         if (flags & NI_NAMEREQD)
255           {
256             __set_errno (serrno);
257             return -1;
258           }
259         else
260           {
261             const char *c;
262             if (sa->sa_family == AF_INET6)
263               c = inet_ntop (AF_INET6,
264                              (void *) &(((struct sockaddr_in6 *) sa)->sin6_addr),
265                              host, hostlen);
266             else
267               c = inet_ntop (AF_INET,
268                              (void *) &(((struct sockaddr_in *) sa)->sin_addr),
269                              host, hostlen);
270
271             if (c == NULL)
272               {
273                 __set_errno (serrno);
274                 return -1;
275               }
276           }
277         break;
278
279       case AF_LOCAL:
280         if (!(flags & NI_NUMERICHOST))
281           {
282             struct utsname utsname;
283
284             if (!uname (&utsname))
285               {
286                 strncpy (host, utsname.nodename, hostlen);
287                 break;
288               };
289           };
290
291         if (flags & NI_NAMEREQD)
292            {
293             __set_errno (serrno);
294             return -1;
295           }
296
297         strncpy (host, "localhost", hostlen);
298         break;
299
300       default:
301         return -1;
302     }
303
304   if (serv && (servlen > 0))
305     switch(sa->sa_family)
306       {
307       case AF_INET:
308       case AF_INET6:
309         if (!(flags & NI_NUMERICSERV))
310           {
311             struct servent *s, ts;
312             while (__getservbyport_r (((struct sockaddr_in *) sa)->sin_port,
313                                       ((flags & NI_DGRAM) ? "udp" : "tcp"),
314                                       &ts, tmpbuf, tmpbuflen, &s))
315               {
316                 if (herrno == NETDB_INTERNAL)
317                   {
318                     if (errno == ERANGE)
319                       {
320                         tmpbuflen *= 2;
321                         tmpbuf = __alloca (tmpbuflen);
322                       }
323                     else
324                       {
325                         __set_errno (serrno);
326                         return -1;
327                       }
328                   }
329                 else
330                   {
331                     break;
332                   }
333               }
334             if (s)
335               {
336                 strncpy (serv, s->s_name, servlen);
337                 break;
338               }
339           }
340         __snprintf (serv, servlen, "%d",
341                     ntohs (((struct sockaddr_in *) sa)->sin_port));
342         break;
343
344       case AF_LOCAL:
345         strncpy (serv, ((struct sockaddr_un *) sa)->sun_path, servlen);
346         break;
347     }
348
349   if (host && (hostlen > 0))
350     host[hostlen-1] = 0;
351   if (serv && (servlen > 0))
352     serv[servlen-1] = 0;
353   errno = serrno;
354   return 0;
355 }