OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-newlib/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [net/] [getnameinfo.c] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 jlechner
/* 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. [The copyright holder has authorized the removal of this clause.]
19
5. Neither the name(s) of the author(s) nor the names of its contributors
20
   may be used to endorse or promote products derived from this software
21
   without specific prior written permission.
22
 
23
THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
 
34
  If these license terms cause you a real problem, contact the author.  */
35
 
36
/* This software is Copyright 1996 by Craig Metz, All Rights Reserved.  */
37
 
38
#include <alloca.h>
39
#include <errno.h>
40
#include <netdb.h>
41
#include <stdlib.h>
42
#include <stdio.h>
43
#include <string.h>
44
#include <unistd.h>
45
#include <arpa/inet.h>
46
#include <net/if.h>
47
#include <netinet/in.h>
48
#include <sys/param.h>
49
#include <sys/socket.h>
50
#include <sys/types.h>
51
#include <sys/un.h>
52
#include <sys/utsname.h>
53
#define _IO_MTSAFE_IO
54
#include <bits/libc-lock.h>
55
#include <libc-symbols.h>
56
#include "local.h"
57
 
58
#ifdef HAVE_LIBIDN
59
# include <libidn/idna.h>
60
extern int __idna_to_unicode_lzlz (const char *input, char **output,
61
                                   int flags);
62
#endif
63
 
64
#ifndef min
65
# define min(x,y) (((x) > (y)) ? (y) : (x))
66
#endif /* min */
67
 
68
libc_freeres_ptr (static char *domain);
69
 
70
 
71
static char *
72
internal_function
73
nrl_domainname (void)
74
{
75
  static int not_first;
76
 
77
  if (! not_first)
78
    {
79
      __libc_lock_define_initialized (static, lock);
80
      __libc_lock_lock (lock);
81
 
82
      if (! not_first)
83
        {
84
          char *c;
85
          struct hostent *h, th;
86
          size_t tmpbuflen = 1024;
87
          char *tmpbuf = alloca (tmpbuflen);
88
          int herror;
89
 
90
          not_first = 1;
91
 
92
          while (__gethostbyname_r ("localhost", &th, tmpbuf, tmpbuflen, &h,
93
                                    &herror))
94
            {
95
              if (herror == NETDB_INTERNAL && errno == ERANGE)
96
                tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
97
              else
98
                break;
99
            }
100
 
101
          if (h && (c = strchr (h->h_name, '.')))
102
            domain = strdup (++c);
103
          else
104
            {
105
              /* The name contains no domain information.  Use the name
106
                 now to get more information.  */
107
              while (__gethostname (tmpbuf, tmpbuflen))
108
                tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
109
 
110
              if ((c = strchr (tmpbuf, '.')))
111
                domain = strdup (++c);
112
              else
113
                {
114
                  /* We need to preserve the hostname.  */
115
                  const char *hstname = alloca (strlen (tmpbuf) + 1);
116
                  strcpy (hstname, tmpbuf);
117
 
118
                  while (__gethostbyname_r (hstname, &th, tmpbuf, tmpbuflen,
119
                                            &h, &herror))
120
                    {
121
                      if (herror == NETDB_INTERNAL && errno == ERANGE)
122
                        tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
123
                                                2 * tmpbuflen);
124
                      else
125
                        break;
126
                    }
127
 
128
                  if (h && (c = strchr(h->h_name, '.')))
129
                    domain = strdup (++c);
130
                  else
131
                    {
132
                      struct in_addr in_addr;
133
 
134
                      in_addr.s_addr = htonl (INADDR_LOOPBACK);
135
 
136
                      while (__gethostbyaddr_r ((const char *) &in_addr,
137
                                                sizeof (struct in_addr),
138
                                                AF_INET, &th, tmpbuf,
139
                                                tmpbuflen, &h, &herror))
140
                        {
141
                          if (herror == NETDB_INTERNAL && errno == ERANGE)
142
                            tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
143
                                                    2 * tmpbuflen);
144
                          else
145
                            break;
146
                        }
147
 
148
                      if (h && (c = strchr (h->h_name, '.')))
149
                        domain = strdup (++c);
150
                    }
151
                }
152
            }
153
        }
154
 
155
      __libc_lock_unlock (lock);
156
    }
157
 
158
  return domain;
159
};
160
 
161
 
162
int
163
getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
164
             socklen_t hostlen, char *serv, socklen_t servlen,
165
             unsigned int flags)
166
{
167
  int serrno = errno;
168
  int tmpbuflen = 1024;
169
  int herrno;
170
  char *tmpbuf = alloca (tmpbuflen);
171
  struct hostent th;
172
  int ok = 0;
173
 
174
  if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM
175
#ifdef HAVE_LIBIDN
176
                |NI_IDN|NI_IDN_ALLOW_UNASSIGNED|NI_IDN_USE_STD3_ASCII_RULES
177
#endif
178
                ))
179
    return EAI_BADFLAGS;
180
 
181
  if (sa == NULL || addrlen < sizeof (sa_family_t))
182
    return EAI_FAMILY;
183
 
184
  switch (sa->sa_family)
185
    {
186
    case AF_LOCAL:
187
      if (addrlen < (socklen_t) (((struct sockaddr_un *) NULL)->sun_path))
188
        return EAI_FAMILY;
189
      break;
190
    case AF_INET:
191
      if (addrlen < sizeof (struct sockaddr_in))
192
        return EAI_FAMILY;
193
      break;
194
    case AF_INET6:
195
      if (addrlen < sizeof (struct sockaddr_in6))
196
        return EAI_FAMILY;
197
      break;
198
    default:
199
      return EAI_FAMILY;
200
    }
201
 
202
  if (host != NULL && hostlen > 0)
203
    switch (sa->sa_family)
204
      {
205
      case AF_INET:
206
      case AF_INET6:
207
        if (!(flags & NI_NUMERICHOST))
208
          {
209
            struct hostent *h = NULL;
210
            if (h == NULL)
211
              {
212
                if (sa->sa_family == AF_INET6)
213
                  {
214
                    while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
215
                                              sizeof(struct in6_addr),
216
                                              AF_INET6, &th, tmpbuf, tmpbuflen,
217
                                              &h, &herrno))
218
                      {
219
                        if (herrno == NETDB_INTERNAL)
220
                          {
221
                            if (errno == ERANGE)
222
                              tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
223
                                                      2 * tmpbuflen);
224
                            else
225
                              {
226
                                h_errno = (herrno);
227
                                errno = (serrno);
228
                                return EAI_SYSTEM;
229
                              }
230
                          }
231
                        else
232
                          {
233
                            break;
234
                          }
235
                      }
236
                  }
237
                else
238
                  {
239
                    while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
240
                                              sizeof(struct in_addr), AF_INET,
241
                                              &th, tmpbuf, tmpbuflen,
242
                                              &h, &herrno))
243
                      {
244
                        if (errno == ERANGE)
245
                          tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
246
                                                  2 * tmpbuflen);
247
                        else
248
                          {
249
                            break;
250
                          }
251
                      }
252
                  }
253
              }
254
 
255
            if (h)
256
              {
257
                char *c;
258
                if ((flags & NI_NOFQDN)
259
                    && (c = nrl_domainname ())
260
                    && (c = strstr (h->h_name, c))
261
                    && (c != h->h_name) && (*(--c) == '.'))
262
                  /* Terminate the string after the prefix.  */
263
                  *c = '\0';
264
 
265
#ifdef HAVE_LIBIDN
266
                /* If requested, convert from the IDN format.  */
267
                if (flags & NI_IDN)
268
                  {
269
                    int idn_flags = 0;
270
                    if  (flags & NI_IDN_ALLOW_UNASSIGNED)
271
                      idn_flags |= IDNA_ALLOW_UNASSIGNED;
272
                    if (flags & NI_IDN_USE_STD3_ASCII_RULES)
273
                      idn_flags |= IDNA_USE_STD3_ASCII_RULES;
274
 
275
                    char *out;
276
                    int rc = __idna_to_unicode_lzlz (h->h_name, &out,
277
                                                     idn_flags);
278
                    if (rc != IDNA_SUCCESS)
279
                      {
280
                        if (rc == IDNA_MALLOC_ERROR)
281
                          return EAI_MEMORY;
282
                        if (rc == IDNA_DLOPEN_ERROR)
283
                          return EAI_SYSTEM;
284
                        return EAI_IDN_ENCODE;
285
                      }
286
 
287
                    if (out != h->h_name)
288
                      {
289
                        h->h_name = strdupa (out);
290
                        free (out);
291
                      }
292
                  }
293
#endif
294
 
295
                size_t len = strlen (h->h_name) + 1;
296
                if (len > hostlen)
297
                  return EAI_OVERFLOW;
298
 
299
                memcpy (host, h->h_name, len);
300
 
301
                ok = 1;
302
              }
303
          }
304
 
305
        if (!ok)
306
          {
307
            if (flags & NI_NAMEREQD)
308
              {
309
                __set_errno (serrno);
310
                return EAI_NONAME;
311
              }
312
            else
313
              {
314
                const char *c;
315
                if (sa->sa_family == AF_INET6)
316
                  {
317
                    const struct sockaddr_in6 *sin6p;
318
                    uint32_t scopeid;
319
 
320
                    sin6p = (const struct sockaddr_in6 *) sa;
321
 
322
                    c = inet_ntop (AF_INET6,
323
                                   (const void *) &sin6p->sin6_addr, host, hostlen);
324
                    scopeid = sin6p->sin6_scope_id;
325
                    if (scopeid != 0)
326
                      {
327
                        /* Buffer is >= IFNAMSIZ+1.  */
328
                        char scopebuf[IFNAMSIZ + 1];
329
                        char *scopeptr;
330
                        int ni_numericscope = 0;
331
                        size_t real_hostlen = strnlen (host, hostlen);
332
                        size_t scopelen = 0;
333
 
334
                        scopebuf[0] = SCOPE_DELIMITER;
335
                        scopebuf[1] = '\0';
336
                        scopeptr = &scopebuf[1];
337
 
338
                        if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
339
                            || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
340
                          {
341
                            if (if_indextoname (scopeid, scopeptr) == NULL)
342
                              ++ni_numericscope;
343
                            else
344
                              scopelen = strlen (scopebuf);
345
                          }
346
                        else
347
                          ++ni_numericscope;
348
 
349
                        if (ni_numericscope)
350
                          scopelen = 1 + snprintf (scopeptr,
351
                                                     (scopebuf
352
                                                      + sizeof scopebuf
353
                                                      - scopeptr),
354
                                                     "%u", scopeid);
355
 
356
                        if (real_hostlen + scopelen + 1 > hostlen)
357
                          /* XXX We should not fail here.  Simply enlarge
358
                             the buffer or return with out of memory.  */
359
                          return EAI_SYSTEM;
360
                        memcpy (host + real_hostlen, scopebuf, scopelen + 1);
361
                      }
362
                  }
363
                else
364
                  c = inet_ntop (AF_INET,
365
                                 (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
366
                                 host, hostlen);
367
                if (c == NULL)
368
                  {
369
                    __set_errno (serrno);
370
                    return EAI_SYSTEM;
371
                  }
372
              }
373
            ok = 1;
374
          }
375
        break;
376
 
377
      case AF_LOCAL:
378
        if (!(flags & NI_NUMERICHOST))
379
          {
380
            struct utsname utsname;
381
 
382
            if (!uname (&utsname))
383
              {
384
                strncpy (host, utsname.nodename, hostlen);
385
                break;
386
              };
387
          };
388
 
389
        if (flags & NI_NAMEREQD)
390
           {
391
            __set_errno (serrno);
392
            return EAI_NONAME;
393
          }
394
 
395
        strncpy (host, "localhost", hostlen);
396
        break;
397
 
398
      default:
399
        return EAI_FAMILY;
400
    }
401
 
402
  if (serv && (servlen > 0))
403
    switch (sa->sa_family)
404
      {
405
      case AF_INET:
406
      case AF_INET6:
407
        if (!(flags & NI_NUMERICSERV))
408
          {
409
            struct servent *s, ts;
410
            while (__getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
411
                                      ((flags & NI_DGRAM) ? "udp" : "tcp"),
412
                                      &ts, tmpbuf, tmpbuflen, &s))
413
              {
414
                if (herrno == NETDB_INTERNAL)
415
                  {
416
                    if (errno == ERANGE)
417
                      tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
418
                                              2 * tmpbuflen);
419
                    else
420
                      {
421
                        __set_errno (serrno);
422
                        return EAI_SYSTEM;
423
                      }
424
                  }
425
                else
426
                  {
427
                    break;
428
                  }
429
              }
430
            if (s)
431
              {
432
                strncpy (serv, s->s_name, servlen);
433
                break;
434
              }
435
          }
436
 
437
        if (snprintf (serv, servlen, "%d",
438
                        ntohs (((const struct sockaddr_in *) sa)->sin_port))
439
            + 1 > servlen)
440
          return EAI_OVERFLOW;
441
 
442
        break;
443
 
444
      case AF_LOCAL:
445
        strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
446
        break;
447
    }
448
 
449
  if (host && (hostlen > 0))
450
    host[hostlen-1] = 0;
451
  if (serv && (servlen > 0))
452
    serv[servlen-1] = 0;
453
  errno = serrno;
454
  return 0;
455
}
456
libc_hidden_def (getnameinfo)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.