~ubuntu-branches/ubuntu/lucid/curl/lucid-security

« back to all changes in this revision

Viewing changes to lib/hostthre.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2009-04-29 11:10:29 UTC
  • mfrom: (3.2.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090429111029-2j5eiyokfw2bw049
Tags: 7.19.4-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Drop build dependencies: stunnel, libdb4.6-dev, libssh2-1-dev
  - Add build-dependency on openssh-server
  - Drop libssh2-1-dev from libcurl4-openssl-dev's Depends.
  - Call automake-1.9 with --add-missing --copy --force
* drop debian/patches/security_CVE-2009-0037.patch 
  - this patch is part of 7.19.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: hostthre.c,v 1.51 2008-02-10 04:20:10 yangtse Exp $
 
21
 * $Id: hostthre.c,v 1.57 2008-11-06 17:19:57 yangtse Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
#include "setup.h"
53
53
#include <stdlib.h>
54
54
#endif
55
55
 
56
 
#ifdef HAVE_SETJMP_H
57
 
#include <setjmp.h>
58
 
#endif
59
 
 
60
56
#ifdef HAVE_PROCESS_H
61
57
#include <process.h>
62
58
#endif
74
70
#include "strerror.h"
75
71
#include "url.h"
76
72
#include "multiif.h"
 
73
#include "inet_pton.h"
77
74
 
78
75
#define _MPRINTF_REPLACE /* use our functions only */
79
76
#include <curl/mprintf.h>
96
93
/* This function is used to init a threaded resolve */
97
94
static bool init_resolve_thread(struct connectdata *conn,
98
95
                                const char *hostname, int port,
99
 
                                const Curl_addrinfo *hints);
 
96
                                const struct addrinfo *hints);
100
97
 
101
98
#ifdef CURLRES_IPV4
102
99
  #define THREAD_FUNC  gethostbyname_thread
106
103
  #define THREAD_NAME "getaddrinfo_thread"
107
104
#endif
108
105
 
109
 
#if defined(DEBUG_THREADING_GETHOSTBYNAME) || \
110
 
    defined(DEBUG_THREADING_GETADDRINFO)
111
 
/* If this is defined, provide tracing */
112
 
#define TRACE(args)  \
113
 
 do { trace_it("%u: ", __LINE__); trace_it args; } while(0)
114
 
 
115
 
static void trace_it (const char *fmt, ...)
116
 
{
117
 
  static int do_trace = -1;
118
 
  va_list args;
119
 
 
120
 
  if(do_trace == -1) {
121
 
    const char *env = getenv("CURL_TRACE");
122
 
    do_trace = (env && atoi(env) > 0);
123
 
  }
124
 
  if(!do_trace)
125
 
    return;
126
 
  va_start (args, fmt);
127
 
  vfprintf (stderr, fmt, args);
128
 
  fflush (stderr);
129
 
  va_end (args);
130
 
}
131
 
#else
132
 
#define TRACE(x)
133
 
#endif
134
 
 
135
 
#ifdef DEBUG_THREADING_GETADDRINFO
136
 
static void dump_addrinfo (struct connectdata *conn, const struct addrinfo *ai)
137
 
{
138
 
  TRACE(("dump_addrinfo:\n"));
139
 
  for ( ; ai; ai = ai->ai_next) {
140
 
    char  buf [INET6_ADDRSTRLEN];
141
 
 
142
 
    trace_it("    fam %2d, CNAME %s, ",
143
 
             ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
144
 
    if(Curl_printable_address(ai, buf, sizeof(buf)))
145
 
      trace_it("%s\n", buf);
146
 
    else
147
 
      trace_it("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
148
 
  }
149
 
}
150
 
#endif
151
 
 
152
106
struct thread_data {
153
107
  HANDLE thread_hnd;
154
108
  unsigned thread_id;
312
266
    else {
313
267
      rc = Curl_addrinfo4_callback(conn, SOCKERRNO, NULL);
314
268
    }
315
 
    TRACE(("Winsock-error %d, addr %s\n", conn->async.status,
316
 
           he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown"));
317
269
    release_thread_sync(&tsd);
318
270
  }
319
271
 
337
289
{
338
290
  struct connectdata *conn = (struct connectdata*) arg;
339
291
  struct thread_data *td   = (struct thread_data*) conn->async.os_specific;
340
 
  struct addrinfo    *res;
 
292
  Curl_addrinfo      *res;
341
293
  char   service [NI_MAXSERV];
342
294
  int    rc;
343
295
  struct addrinfo hints = td->hints;
362
314
     need */
363
315
  SetEvent(td->event_thread_started);
364
316
 
365
 
  rc = getaddrinfo(tsd.hostname, service, &hints, &res);
 
317
  rc = Curl_getaddrinfo_ex(tsd.hostname, service, &hints, &res);
366
318
 
367
319
  /* is parent thread waiting for us and are we able to access conn members? */
368
320
  if(acquire_thread_sync(&tsd)) {
371
323
    SetEvent(td->event_resolved);
372
324
 
373
325
    if(rc == 0) {
374
 
#ifdef DEBUG_THREADING_GETADDRINFO
375
 
      dump_addrinfo (conn, res);
376
 
#endif
377
326
      rc = Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
378
327
    }
379
328
    else {
380
329
      rc = Curl_addrinfo6_callback(conn, SOCKERRNO, NULL);
381
 
      TRACE(("Winsock-error %d, no address\n", conn->async.status));
382
330
    }
383
331
    release_thread_sync(&tsd);
384
332
  }
449
397
 */
450
398
static bool init_resolve_thread (struct connectdata *conn,
451
399
                                 const char *hostname, int port,
452
 
                                 const Curl_addrinfo *hints)
 
400
                                 const struct addrinfo *hints)
453
401
{
454
402
  struct thread_data *td = calloc(sizeof(*td), 1);
455
403
  HANDLE thread_and_event[2] = {0};
536
484
#endif
537
485
 
538
486
  if(!td->thread_hnd) {
539
 
#ifdef _WIN32_WCE
540
 
     TRACE(("CreateThread() failed; %s\n", Curl_strerror(conn, ERRNO)));
541
 
#else
 
487
#ifndef _WIN32_WCE
542
488
     SET_ERRNO(errno);
543
 
     TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn, ERRNO)));
544
489
#endif
545
490
     Curl_destroy_thread_data(&conn->async);
546
491
     return FALSE;
580
525
  struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
581
526
  struct SessionHandle *data = conn->data;
582
527
  long   timeout;
583
 
  DWORD  status, ticks;
 
528
  DWORD  status;
584
529
  CURLcode rc;
585
530
 
586
531
  DEBUGASSERT(conn && td);
591
536
    conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
592
537
    conn->data->set.timeout ? conn->data->set.timeout :
593
538
    CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
594
 
  ticks = GetTickCount();
595
539
 
596
540
  /* wait for the thread to resolve the name */
597
541
  status = WaitForSingleObject(td->event_resolved, timeout);
614
558
      TerminateThread(td->thread_hnd, 0);
615
559
      conn->async.done = TRUE;
616
560
      td->thread_status = (DWORD)-1;
617
 
      TRACE(("%s() thread stuck?!, ", THREAD_NAME));
618
561
    }
619
562
    else {
620
563
      /* Thread finished before timeout; propagate Winsock error to this
623
566
       */
624
567
      SET_SOCKERRNO(conn->async.status);
625
568
      GetExitCodeThread(td->thread_hnd, &td->thread_status);
626
 
      TRACE(("%s() status %lu, thread retval %lu, ",
627
 
             THREAD_NAME, status, td->thread_status));
628
569
    }
629
570
  }
630
571
  else {
631
572
    conn->async.done = TRUE;
632
573
    td->thread_status = (DWORD)-1;
633
 
    TRACE(("%s() timeout, ", THREAD_NAME));
634
574
  }
635
575
 
636
 
  TRACE(("elapsed %lu ms\n", GetTickCount()-ticks));
637
 
 
638
576
  if(entry)
639
577
    *entry = conn->async.dns;
640
578
 
690
628
    /* we're done */
691
629
    Curl_destroy_thread_data(&conn->async);
692
630
    if(!conn->async.dns) {
693
 
      TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n"));
694
631
      failf(data, "Could not resolve host: %s; %s",
695
632
            conn->host.name, Curl_strerror(conn, conn->async.status));
696
633
      return CURLE_COULDNT_RESOLVE_HOST;
697
634
    }
698
635
    *entry = conn->async.dns;
699
 
    TRACE(("resolved okay, dns %p\n", *entry));
700
636
  }
701
637
  return CURLE_OK;
702
638
}
730
666
{
731
667
  struct hostent *h = NULL;
732
668
  struct SessionHandle *data = conn->data;
733
 
  in_addr_t in;
 
669
  struct in_addr in;
734
670
 
735
671
  *waitp = 0; /* don't wait, we act synchronously */
736
672
 
737
 
  in = inet_addr(hostname);
738
 
  if(in != CURL_INADDR_NONE)
 
673
  if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
739
674
    /* This is a dotted IP address 123.123.123.123-style */
740
 
    return Curl_ip2addr(in, hostname, port);
 
675
    return Curl_ip2addr(AF_INET, &in, hostname, port);
741
676
 
742
677
  /* fire up a new resolver thread! */
743
678
  if(init_resolve_thread(conn, hostname, port, NULL)) {
768
703
                                int port,
769
704
                                int *waitp)
770
705
{
771
 
  struct addrinfo hints, *res;
 
706
  struct addrinfo hints;
 
707
  Curl_addrinfo *res;
772
708
  int error;
773
709
  char sbuf[NI_MAXSERV];
774
 
  curl_socket_t s;
775
710
  int pf;
776
711
  struct SessionHandle *data = conn->data;
777
712
 
778
713
  *waitp = FALSE; /* default to synch response */
779
714
 
780
 
  /* see if we have an IPv6 stack */
781
 
  s = socket(PF_INET6, SOCK_DGRAM, 0);
782
 
  if(s == CURL_SOCKET_BAD) {
783
 
    /* Some non-IPv6 stacks have been found to make very slow name resolves
784
 
     * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
785
 
     * the stack seems to be a non-ipv6 one. */
786
 
 
 
715
  /*
 
716
   * Check if a limited name resolve has been requested.
 
717
   */
 
718
  switch(data->set.ip_version) {
 
719
  case CURL_IPRESOLVE_V4:
787
720
    pf = PF_INET;
 
721
    break;
 
722
  case CURL_IPRESOLVE_V6:
 
723
    pf = PF_INET6;
 
724
    break;
 
725
  default:
 
726
    pf = PF_UNSPEC;
 
727
    break;
788
728
  }
789
 
  else {
790
 
    /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
791
 
     * possible checks. And close the socket again.
792
 
     */
793
 
    sclose(s);
794
 
 
795
 
    /*
796
 
     * Check if a more limited name resolve has been requested.
797
 
     */
798
 
    switch(data->set.ip_version) {
799
 
    case CURL_IPRESOLVE_V4:
 
729
 
 
730
  if (pf != PF_INET) {
 
731
    /* see if we have an IPv6 stack */
 
732
    curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
 
733
    if(s == CURL_SOCKET_BAD) {
 
734
      /* Some non-IPv6 stacks have been found to make very slow name resolves
 
735
       * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
 
736
       * the stack seems to be a non-ipv6 one. */
 
737
 
800
738
      pf = PF_INET;
801
 
      break;
802
 
    case CURL_IPRESOLVE_V6:
803
 
      pf = PF_INET6;
804
 
      break;
805
 
    default:
806
 
      pf = PF_UNSPEC;
807
 
      break;
 
739
    }
 
740
    else {
 
741
      /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
 
742
       * possible checks. And close the socket again.
 
743
       */
 
744
      sclose(s);
808
745
    }
809
746
  }
810
747
 
826
763
  infof(data, "init_resolve_thread() failed for %s; %s\n",
827
764
        hostname, Curl_strerror(conn, ERRNO));
828
765
 
829
 
  error = getaddrinfo(hostname, sbuf, &hints, &res);
 
766
  error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
830
767
  if(error) {
831
768
    infof(data, "getaddrinfo() failed for %s:%d; %s\n",
832
769
          hostname, port, Curl_strerror(conn, SOCKERRNO));