~ubuntu-branches/ubuntu/precise/wget/precise-proposed

« back to all changes in this revision

Viewing changes to lib/getaddrinfo.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-10-19 00:00:09 UTC
  • mfrom: (2.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20111019000009-8p33w3wz4b1rdri0
Tags: 1.13-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.
  - Depend on libssl-dev 0.9.8k-7ubuntu4 (LP: #503339)
* Dropped changes, superseded in Debian:
  - Keep build dependencies in main:
    + debian/control: remove info2man build-dep
    + debian/patches/series: disable wget-infopod_generated_manpage
  - Mark wget Multi-Arch: foreign, so packages that aren't of the same arch
    can depend on it.
* Pass --with-ssl=openssl; we don't want to use gnutls, there's no udeb for
  it.
* Add a second build pass for the udeb, so we can build without libidn.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- buffer-read-only: t -*- vi: set ro: */
 
2
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
 
3
/* Get address information (partial implementation).
 
4
   Copyright (C) 1997, 2001-2002, 2004-2011 Free Software Foundation, Inc.
 
5
   Contributed by Simon Josefsson <simon@josefsson.org>.
 
6
 
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 3, or (at your option)
 
10
   any later version.
 
11
 
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program; if not, write to the Free Software Foundation,
 
19
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
20
 
 
21
#include <config.h>
 
22
 
 
23
/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
 
24
   optimizes away the sa == NULL test below.  */
 
25
#define _GL_ARG_NONNULL(params)
 
26
 
 
27
#include <netdb.h>
 
28
 
 
29
#if HAVE_NETINET_IN_H
 
30
# include <netinet/in.h>
 
31
#endif
 
32
 
 
33
/* Get inet_ntop.  */
 
34
#include <arpa/inet.h>
 
35
 
 
36
/* Get calloc. */
 
37
#include <stdlib.h>
 
38
 
 
39
/* Get memcpy, strdup. */
 
40
#include <string.h>
 
41
 
 
42
/* Get snprintf. */
 
43
#include <stdio.h>
 
44
 
 
45
#include <stdbool.h>
 
46
 
 
47
#include "gettext.h"
 
48
#define _(String) gettext (String)
 
49
#define N_(String) String
 
50
 
 
51
/* BeOS has AF_INET, but not PF_INET.  */
 
52
#ifndef PF_INET
 
53
# define PF_INET AF_INET
 
54
#endif
 
55
/* BeOS also lacks PF_UNSPEC.  */
 
56
#ifndef PF_UNSPEC
 
57
# define PF_UNSPEC 0
 
58
#endif
 
59
 
 
60
#if defined _WIN32 || defined __WIN32__
 
61
# define WIN32_NATIVE
 
62
#endif
 
63
 
 
64
/* gl_sockets_startup */
 
65
#include "sockets.h"
 
66
 
 
67
#ifdef WIN32_NATIVE
 
68
typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
 
69
                                        const struct addrinfo*,
 
70
                                        struct addrinfo**);
 
71
typedef void (WSAAPI *freeaddrinfo_func) (struct addrinfo*);
 
72
typedef int (WSAAPI *getnameinfo_func) (const struct sockaddr*,
 
73
                                        socklen_t, char*, DWORD,
 
74
                                        char*, DWORD, int);
 
75
 
 
76
static getaddrinfo_func getaddrinfo_ptr = NULL;
 
77
static freeaddrinfo_func freeaddrinfo_ptr = NULL;
 
78
static getnameinfo_func getnameinfo_ptr = NULL;
 
79
 
 
80
static int
 
81
use_win32_p (void)
 
82
{
 
83
  static int done = 0;
 
84
  HMODULE h;
 
85
 
 
86
  if (done)
 
87
    return getaddrinfo_ptr ? 1 : 0;
 
88
 
 
89
  done = 1;
 
90
 
 
91
  h = GetModuleHandle ("ws2_32.dll");
 
92
 
 
93
  if (h)
 
94
    {
 
95
      getaddrinfo_ptr = (getaddrinfo_func) GetProcAddress (h, "getaddrinfo");
 
96
      freeaddrinfo_ptr = (freeaddrinfo_func) GetProcAddress (h, "freeaddrinfo");
 
97
      getnameinfo_ptr = (getnameinfo_func) GetProcAddress (h, "getnameinfo");
 
98
    }
 
99
 
 
100
  /* If either is missing, something is odd. */
 
101
  if (!getaddrinfo_ptr || !freeaddrinfo_ptr || !getnameinfo_ptr)
 
102
    {
 
103
      getaddrinfo_ptr = NULL;
 
104
      freeaddrinfo_ptr = NULL;
 
105
      getnameinfo_ptr = NULL;
 
106
      return 0;
 
107
    }
 
108
 
 
109
  gl_sockets_startup (SOCKETS_1_1);
 
110
 
 
111
  return 1;
 
112
}
 
113
#endif
 
114
 
 
115
static inline bool
 
116
validate_family (int family)
 
117
{
 
118
  /* FIXME: Support more families. */
 
119
#if HAVE_IPV4
 
120
     if (family == PF_INET)
 
121
       return true;
 
122
#endif
 
123
#if HAVE_IPV6
 
124
     if (family == PF_INET6)
 
125
       return true;
 
126
#endif
 
127
     if (family == PF_UNSPEC)
 
128
       return true;
 
129
     return false;
 
130
}
 
131
 
 
132
/* Translate name of a service location and/or a service name to set of
 
133
   socket addresses. */
 
134
int
 
135
getaddrinfo (const char *restrict nodename,
 
136
             const char *restrict servname,
 
137
             const struct addrinfo *restrict hints,
 
138
             struct addrinfo **restrict res)
 
139
{
 
140
  struct addrinfo *tmp;
 
141
  int port = 0;
 
142
  struct hostent *he;
 
143
  void *storage;
 
144
  size_t size;
 
145
#if HAVE_IPV6
 
146
  struct v6_pair {
 
147
    struct addrinfo addrinfo;
 
148
    struct sockaddr_in6 sockaddr_in6;
 
149
  };
 
150
#endif
 
151
#if HAVE_IPV4
 
152
  struct v4_pair {
 
153
    struct addrinfo addrinfo;
 
154
    struct sockaddr_in sockaddr_in;
 
155
  };
 
156
#endif
 
157
 
 
158
#ifdef WIN32_NATIVE
 
159
  if (use_win32_p ())
 
160
    return getaddrinfo_ptr (nodename, servname, hints, res);
 
161
#endif
 
162
 
 
163
  if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE)))
 
164
    /* FIXME: Support more flags. */
 
165
    return EAI_BADFLAGS;
 
166
 
 
167
  if (hints && !validate_family (hints->ai_family))
 
168
    return EAI_FAMILY;
 
169
 
 
170
  if (hints &&
 
171
      hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM)
 
172
    /* FIXME: Support other socktype. */
 
173
    return EAI_SOCKTYPE; /* FIXME: Better return code? */
 
174
 
 
175
  if (!nodename)
 
176
    {
 
177
      if (!(hints->ai_flags & AI_PASSIVE))
 
178
        return EAI_NONAME;
 
179
 
 
180
#ifdef HAVE_IPV6
 
181
      nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
 
182
#else
 
183
      nodename = "0.0.0.0";
 
184
#endif
 
185
    }
 
186
 
 
187
  if (servname)
 
188
    {
 
189
      struct servent *se = NULL;
 
190
      const char *proto =
 
191
        (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
 
192
 
 
193
      if (hints == NULL || !(hints->ai_flags & AI_NUMERICSERV))
 
194
        /* FIXME: Use getservbyname_r if available. */
 
195
        se = getservbyname (servname, proto);
 
196
 
 
197
      if (!se)
 
198
        {
 
199
          char *c;
 
200
          if (!(*servname >= '0' && *servname <= '9'))
 
201
            return EAI_NONAME;
 
202
          port = strtoul (servname, &c, 10);
 
203
          if (*c || port > 0xffff)
 
204
            return EAI_NONAME;
 
205
          port = htons (port);
 
206
        }
 
207
      else
 
208
        port = se->s_port;
 
209
    }
 
210
 
 
211
  /* FIXME: Use gethostbyname_r if available. */
 
212
  he = gethostbyname (nodename);
 
213
  if (!he || he->h_addr_list[0] == NULL)
 
214
    return EAI_NONAME;
 
215
 
 
216
  switch (he->h_addrtype)
 
217
    {
 
218
#if HAVE_IPV6
 
219
    case PF_INET6:
 
220
      size = sizeof (struct v6_pair);
 
221
      break;
 
222
#endif
 
223
 
 
224
#if HAVE_IPV4
 
225
    case PF_INET:
 
226
      size = sizeof (struct v4_pair);
 
227
      break;
 
228
#endif
 
229
 
 
230
    default:
 
231
      return EAI_NODATA;
 
232
    }
 
233
 
 
234
  storage = calloc (1, size);
 
235
  if (!storage)
 
236
    return EAI_MEMORY;
 
237
 
 
238
  switch (he->h_addrtype)
 
239
    {
 
240
#if HAVE_IPV6
 
241
    case PF_INET6:
 
242
      {
 
243
        struct v6_pair *p = storage;
 
244
        struct sockaddr_in6 *sinp = &p->sockaddr_in6;
 
245
        tmp = &p->addrinfo;
 
246
 
 
247
        if (port)
 
248
          sinp->sin6_port = port;
 
249
 
 
250
        if (he->h_length != sizeof (sinp->sin6_addr))
 
251
          {
 
252
            free (storage);
 
253
            return EAI_SYSTEM; /* FIXME: Better return code?  Set errno? */
 
254
          }
 
255
 
 
256
        memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr);
 
257
 
 
258
        tmp->ai_addr = (struct sockaddr *) sinp;
 
259
        tmp->ai_addrlen = sizeof *sinp;
 
260
      }
 
261
      break;
 
262
#endif
 
263
 
 
264
#if HAVE_IPV4
 
265
    case PF_INET:
 
266
      {
 
267
        struct v4_pair *p = storage;
 
268
        struct sockaddr_in *sinp = &p->sockaddr_in;
 
269
        tmp = &p->addrinfo;
 
270
 
 
271
        if (port)
 
272
          sinp->sin_port = port;
 
273
 
 
274
        if (he->h_length != sizeof (sinp->sin_addr))
 
275
          {
 
276
            free (storage);
 
277
            return EAI_SYSTEM; /* FIXME: Better return code?  Set errno? */
 
278
          }
 
279
 
 
280
        memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr);
 
281
 
 
282
        tmp->ai_addr = (struct sockaddr *) sinp;
 
283
        tmp->ai_addrlen = sizeof *sinp;
 
284
      }
 
285
      break;
 
286
#endif
 
287
 
 
288
    default:
 
289
      free (storage);
 
290
      return EAI_NODATA;
 
291
    }
 
292
 
 
293
  if (hints && hints->ai_flags & AI_CANONNAME)
 
294
    {
 
295
      const char *cn;
 
296
      if (he->h_name)
 
297
        cn = he->h_name;
 
298
      else
 
299
        cn = nodename;
 
300
 
 
301
      tmp->ai_canonname = strdup (cn);
 
302
      if (!tmp->ai_canonname)
 
303
        {
 
304
          free (storage);
 
305
          return EAI_MEMORY;
 
306
        }
 
307
    }
 
308
 
 
309
  tmp->ai_protocol = (hints) ? hints->ai_protocol : 0;
 
310
  tmp->ai_socktype = (hints) ? hints->ai_socktype : 0;
 
311
  tmp->ai_addr->sa_family = he->h_addrtype;
 
312
  tmp->ai_family = he->h_addrtype;
 
313
 
 
314
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
 
315
  switch (he->h_addrtype)
 
316
    {
 
317
#if HAVE_IPV4
 
318
    case AF_INET:
 
319
      tmp->ai_addr->sa_len = sizeof (struct sockaddr_in);
 
320
      break;
 
321
#endif
 
322
#if HAVE_IPV6
 
323
    case AF_INET6:
 
324
      tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6);
 
325
      break;
 
326
#endif
 
327
    }
 
328
#endif
 
329
 
 
330
  /* FIXME: If more than one address, create linked list of addrinfo's. */
 
331
 
 
332
  *res = tmp;
 
333
 
 
334
  return 0;
 
335
}
 
336
 
 
337
/* Free `addrinfo' structure AI including associated storage.  */
 
338
void
 
339
freeaddrinfo (struct addrinfo *ai)
 
340
{
 
341
#ifdef WIN32_NATIVE
 
342
  if (use_win32_p ())
 
343
    {
 
344
      freeaddrinfo_ptr (ai);
 
345
      return;
 
346
    }
 
347
#endif
 
348
 
 
349
  while (ai)
 
350
    {
 
351
      struct addrinfo *cur;
 
352
 
 
353
      cur = ai;
 
354
      ai = ai->ai_next;
 
355
 
 
356
      free (cur->ai_canonname);
 
357
      free (cur);
 
358
    }
 
359
}
 
360
 
 
361
int
 
362
getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
 
363
             char *restrict node, socklen_t nodelen,
 
364
             char *restrict service, socklen_t servicelen,
 
365
             int flags)
 
366
{
 
367
#ifdef WIN32_NATIVE
 
368
  if (use_win32_p ())
 
369
    return getnameinfo_ptr (sa, salen, node, nodelen,
 
370
                            service, servicelen, flags);
 
371
#endif
 
372
 
 
373
  /* FIXME: Support other flags. */
 
374
  if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) ||
 
375
      (service && servicelen > 0 && !(flags & NI_NUMERICHOST)) ||
 
376
      (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV)))
 
377
    return EAI_BADFLAGS;
 
378
 
 
379
  if (sa == NULL || salen < sizeof (sa->sa_family))
 
380
    return EAI_FAMILY;
 
381
 
 
382
  switch (sa->sa_family)
 
383
    {
 
384
#if HAVE_IPV4
 
385
    case AF_INET:
 
386
      if (salen < sizeof (struct sockaddr_in))
 
387
        return EAI_FAMILY;
 
388
      break;
 
389
#endif
 
390
#if HAVE_IPV6
 
391
    case AF_INET6:
 
392
      if (salen < sizeof (struct sockaddr_in6))
 
393
        return EAI_FAMILY;
 
394
      break;
 
395
#endif
 
396
    default:
 
397
      return EAI_FAMILY;
 
398
    }
 
399
 
 
400
  if (node && nodelen > 0 && flags & NI_NUMERICHOST)
 
401
    {
 
402
      switch (sa->sa_family)
 
403
        {
 
404
#if HAVE_IPV4
 
405
        case AF_INET:
 
406
          if (!inet_ntop (AF_INET,
 
407
                          &(((const struct sockaddr_in *) sa)->sin_addr),
 
408
                          node, nodelen))
 
409
            return EAI_SYSTEM;
 
410
          break;
 
411
#endif
 
412
 
 
413
#if HAVE_IPV6
 
414
        case AF_INET6:
 
415
          if (!inet_ntop (AF_INET6,
 
416
                          &(((const struct sockaddr_in6 *) sa)->sin6_addr),
 
417
                          node, nodelen))
 
418
            return EAI_SYSTEM;
 
419
          break;
 
420
#endif
 
421
 
 
422
        default:
 
423
          return EAI_FAMILY;
 
424
        }
 
425
    }
 
426
 
 
427
  if (service && servicelen > 0 && flags & NI_NUMERICSERV)
 
428
    switch (sa->sa_family)
 
429
      {
 
430
#if HAVE_IPV4
 
431
      case AF_INET:
 
432
#endif
 
433
#if HAVE_IPV6
 
434
      case AF_INET6:
 
435
#endif
 
436
        {
 
437
          unsigned short int port
 
438
            = ntohs (((const struct sockaddr_in *) sa)->sin_port);
 
439
          if (servicelen <= snprintf (service, servicelen, "%u", port))
 
440
            return EAI_OVERFLOW;
 
441
        }
 
442
        break;
 
443
      }
 
444
 
 
445
  return 0;
 
446
}