159
164
int Curl_num_addresses(const Curl_addrinfo *addr)
162
for (i = 0; addr; addr = addr->ai_next, i++)
168
addr = addr->ai_next;
168
175
* Curl_printable_address() returns a printable version of the 1st address
169
* given in the 'ip' argument. The result will be stored in the buf that is
176
* given in the 'ai' argument. The result will be stored in the buf that is
170
177
* bufsize bytes big.
172
179
* If the conversion fails, it returns NULL.
174
const char *Curl_printable_address(const Curl_addrinfo *ip,
175
char *buf, size_t bufsize)
182
Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
177
const void *ip4 = &((const struct sockaddr_in*)ip->ai_addr)->sin_addr;
178
int af = ip->ai_family;
180
const void *ip6 = &((const struct sockaddr_in6*)ip->ai_addr)->sin6_addr;
182
const void *ip6 = NULL;
184
const struct sockaddr_in *sa4;
185
const struct in_addr *ipaddr4;
187
const struct sockaddr_in6 *sa6;
188
const struct in6_addr *ipaddr6;
185
return Curl_inet_ntop(af, af == AF_INET ? ip4 : ip6, buf, bufsize);
191
switch (ai->ai_family) {
193
sa4 = (const void *)ai->ai_addr;
194
ipaddr4 = &sa4->sin_addr;
195
return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
198
sa6 = (const void *)ai->ai_addr;
199
ipaddr6 = &sa6->sin6_addr;
200
return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize);
500
#ifdef USE_ALARM_TIMEOUT
502
* This signal handler jumps back into the main libcurl code and continues
503
* execution. This effectively causes the remainder of the application to run
504
* within a signal handler which is nonportable and could lead to problems.
507
RETSIGTYPE alarmfunc(int sig)
509
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
511
siglongjmp(curl_jmpenv, 1);
514
#endif /* USE_ALARM_TIMEOUT */
517
* Curl_resolv_timeout() is the same as Curl_resolv() but specifies a
518
* timeout. This function might return immediately if we're using asynch
519
* resolves. See the return codes.
521
* The cache entry we return will get its 'inuse' counter increased when this
522
* function is used. You MUST call Curl_resolv_unlock() later (when you're
523
* done using this struct) to decrease the counter again.
525
* If built with a synchronous resolver and use of signals is not
526
* disabled by the application, then a nonzero timeout will cause a
527
* timeout after the specified number of milliseconds. Otherwise, timeout
532
* CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired
533
* CURLRESOLV_ERROR (-1) = error, no pointer
534
* CURLRESOLV_RESOLVED (0) = OK, pointer provided
535
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
538
int Curl_resolv_timeout(struct connectdata *conn,
539
const char *hostname,
541
struct Curl_dns_entry **entry,
544
#ifdef USE_ALARM_TIMEOUT
545
#ifdef HAVE_SIGACTION
546
struct sigaction keep_sigact; /* store the old struct here */
547
bool keep_copysig=FALSE; /* did copy it? */
548
struct sigaction sigact;
551
void (*keep_sigact)(int); /* store the old handler here */
552
#endif /* HAVE_SIGNAL */
553
#endif /* HAVE_SIGACTION */
554
volatile long timeout;
555
unsigned int prev_alarm=0;
556
struct SessionHandle *data = conn->data;
557
#endif /* USE_ALARM_TIMEOUT */
562
#ifdef USE_ALARM_TIMEOUT
563
if (data->set.no_signal)
564
/* Ignore the timeout when signals are disabled */
569
if(timeout && timeout < 1000)
570
/* The alarm() function only provides integer second resolution, so if
571
we want to wait less than one second we must bail out already now. */
572
return CURLRESOLV_TIMEDOUT;
575
/* This allows us to time-out from the name resolver, as the timeout
576
will generate a signal and we will siglongjmp() from that here.
577
This technique has problems (see alarmfunc). */
578
if(sigsetjmp(curl_jmpenv, 1)) {
579
/* this is coming from a siglongjmp() after an alarm signal */
580
failf(data, "name lookup timed out");
581
return CURLRESOLV_ERROR;
584
/*************************************************************
585
* Set signal handler to catch SIGALRM
586
* Store the old value to be able to set it back later!
587
*************************************************************/
588
#ifdef HAVE_SIGACTION
589
sigaction(SIGALRM, NULL, &sigact);
590
keep_sigact = sigact;
591
keep_copysig = TRUE; /* yes, we have a copy */
592
sigact.sa_handler = alarmfunc;
594
/* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
595
sigact.sa_flags &= ~SA_RESTART;
597
/* now set the new struct */
598
sigaction(SIGALRM, &sigact, NULL);
599
#else /* HAVE_SIGACTION */
600
/* no sigaction(), revert to the much lamer signal() */
602
keep_sigact = signal(SIGALRM, alarmfunc);
604
#endif /* HAVE_SIGACTION */
606
/* alarm() makes a signal get sent when the timeout fires off, and that
607
will abort system calls */
608
prev_alarm = alarm((unsigned int) (timeout/1000L));
612
#ifndef CURLRES_ASYNCH
614
infof(conn->data, "timeout on name lookup is not supported\n");
616
(void)timeoutms; /* timeoutms not used with an async resolver */
618
#endif /* USE_ALARM_TIMEOUT */
620
/* Perform the actual name resolution. This might be interrupted by an
621
* alarm if it takes too long.
623
rc = Curl_resolv(conn, hostname, port, entry);
625
#ifdef USE_ALARM_TIMEOUT
628
#ifdef HAVE_SIGACTION
630
/* we got a struct as it looked before, now put that one back nice
632
sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
636
/* restore the previous SIGALRM handler */
637
signal(SIGALRM, keep_sigact);
639
#endif /* HAVE_SIGACTION */
641
/* switch back the alarm() to either zero or to what it was before minus
642
the time we spent until now! */
644
/* there was an alarm() set before us, now put it back */
645
unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
647
/* the alarm period is counted in even number of seconds */
648
unsigned long alarm_set = prev_alarm - elapsed_ms/1000;
651
((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
652
/* if the alarm time-left reached zero or turned "negative" (counted
653
with unsigned values), we should fire off a SIGALRM here, but we
654
won't, and zero would be to switch it off so we never set it to
657
rc = CURLRESOLV_TIMEDOUT;
658
failf(data, "Previous alarm fired off!");
661
alarm((unsigned int)alarm_set);
664
alarm(0); /* just shut it off */
666
#endif /* USE_ALARM_TIMEOUT */
492
672
* Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
493
673
* made, the struct may be destroyed due to pruning. It is important that only
543
724
return Curl_he2ai(orig, port);
545
726
#endif /* CURLRES_ADDRINFO_COPY */
547
/***********************************************************************
548
* Only for plain-ipv4 and c-ares builds
549
**********************************************************************/
551
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
553
* This is a function for freeing name information in a protocol independent
556
void Curl_freeaddrinfo(Curl_addrinfo *ai)
560
/* walk over the list and free all entries */
564
free(ai->ai_canonname);
571
struct hostent hostentry;
572
char *h_addr_list[2];
573
struct in_addr addrentry;
574
char h_name[16]; /* 123.123.123.123 = 15 letters is maximum */
578
* Curl_ip2addr() takes a 32bit ipv4 internet address as input parameter
579
* together with a pointer to the string version of the address, and it
580
* returns a Curl_addrinfo chain filled in correctly with information for this
583
* The input parameters ARE NOT checked for validity but they are expected
584
* to have been checked already when this is called.
586
Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port)
590
#if defined(VMS) && \
591
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
592
#pragma pointer_size save
593
#pragma pointer_size short
594
#pragma message disable PTRMISMATCH
598
struct in_addr *addrentry;
599
struct namebuf buffer;
600
struct namebuf *buf = &buffer;
603
h->h_addr_list = &buf->h_addr_list[0];
604
addrentry = &buf->addrentry;
606
/* On UNICOS, s_addr is a bit field and for some reason assigning to it
607
* doesn't work. There must be a better fix than this ugly hack.
609
memcpy(addrentry, &num, SIZEOF_in_addr);
611
addrentry->s_addr = num;
613
h->h_addr_list[0] = (char*)addrentry;
614
h->h_addr_list[1] = NULL;
615
h->h_addrtype = AF_INET;
616
h->h_length = sizeof(*addrentry);
617
h->h_name = &buf->h_name[0];
620
/* Now store the dotted version of the address */
621
snprintf((char *)h->h_name, 16, "%s", hostname);
623
#if defined(VMS) && \
624
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
625
#pragma pointer_size restore
626
#pragma message enable PTRMISMATCH
629
ai = Curl_he2ai(h, port);
633
#endif /* CURLRES_IPV4 || CURLRES_ARES */