remove the CVSish $Id$ lines
[platform/upstream/curl.git] / lib / hostip.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 #include "setup.h"
24
25 #include <string.h>
26
27 #ifdef HAVE_SYS_SOCKET_H
28 #include <sys/socket.h>
29 #endif
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
32 #endif
33 #ifdef HAVE_NETDB_H
34 #include <netdb.h>
35 #endif
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
38 #endif
39 #ifdef HAVE_STDLIB_H
40 #include <stdlib.h>     /* required for free() prototypes */
41 #endif
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>     /* for the close() proto */
44 #endif
45 #ifdef __VMS
46 #include <in.h>
47 #include <inet.h>
48 #include <stdlib.h>
49 #endif
50
51 #ifdef HAVE_SETJMP_H
52 #include <setjmp.h>
53 #endif
54 #ifdef HAVE_SIGNAL_H
55 #include <signal.h>
56 #endif
57
58 #ifdef HAVE_PROCESS_H
59 #include <process.h>
60 #endif
61
62 #include "urldata.h"
63 #include "sendf.h"
64 #include "hostip.h"
65 #include "hash.h"
66 #include "share.h"
67 #include "strerror.h"
68 #include "url.h"
69 #include "inet_ntop.h"
70
71 #define _MPRINTF_REPLACE /* use our functions only */
72 #include <curl/mprintf.h>
73
74 #include "curl_memory.h"
75 /* The last #include file should be: */
76 #include "memdebug.h"
77
78 #if defined(CURLRES_SYNCH) && \
79     defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
80 /* alarm-based timeouts can only be used with all the dependencies satisfied */
81 #define USE_ALARM_TIMEOUT
82 #endif
83
84 /*
85  * hostip.c explained
86  * ==================
87  *
88  * The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c
89  * source file are these:
90  *
91  * CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use
92  * that. The host may not be able to resolve IPv6, but we don't really have to
93  * take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4
94  * defined.
95  *
96  * CURLRES_ARES - is defined if libcurl is built to use c-ares for
97  * asynchronous name resolves. This can be Windows or *nix.
98  *
99  * CURLRES_THREADED - is defined if libcurl is built to run under (native)
100  * Windows, and then the name resolve will be done in a new thread, and the
101  * supported API will be the same as for ares-builds.
102  *
103  * If any of the two previous are defined, CURLRES_ASYNCH is defined too. If
104  * libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is
105  * defined.
106  *
107  * The host*.c sources files are split up like this:
108  *
109  * hostip.c   - method-independent resolver functions and utility functions
110  * hostasyn.c - functions for asynchronous name resolves
111  * hostsyn.c  - functions for synchronous name resolves
112  * hostares.c - functions for ares-using name resolves
113  * hostthre.c - functions for threaded name resolves
114  * hostip4.c  - ipv4-specific functions
115  * hostip6.c  - ipv6-specific functions
116  *
117  * The hostip.h is the united header file for all this. It defines the
118  * CURLRES_* defines based on the config*.h and setup.h defines.
119  */
120
121 /* These two symbols are for the global DNS cache */
122 static struct curl_hash hostname_cache;
123 static int host_cache_initialized;
124
125 static void freednsentry(void *freethis);
126
127 /*
128  * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
129  * Global DNS cache is general badness. Do not use. This will be removed in
130  * a future version. Use the share interface instead!
131  *
132  * Returns a struct curl_hash pointer on success, NULL on failure.
133  */
134 struct curl_hash *Curl_global_host_cache_init(void)
135 {
136   int rc = 0;
137   if(!host_cache_initialized) {
138     rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str,
139                         Curl_str_key_compare, freednsentry);
140     if(!rc)
141       host_cache_initialized = 1;
142   }
143   return rc?NULL:&hostname_cache;
144 }
145
146 /*
147  * Destroy and cleanup the global DNS cache
148  */
149 void Curl_global_host_cache_dtor(void)
150 {
151   if(host_cache_initialized) {
152     Curl_hash_clean(&hostname_cache);
153     host_cache_initialized = 0;
154   }
155 }
156
157 /*
158  * Return # of adresses in a Curl_addrinfo struct
159  */
160 int Curl_num_addresses(const Curl_addrinfo *addr)
161 {
162   int i = 0;
163   while(addr) {
164     addr = addr->ai_next;
165     i++;
166   }
167   return i;
168 }
169
170 /*
171  * Curl_printable_address() returns a printable version of the 1st address
172  * given in the 'ai' argument. The result will be stored in the buf that is
173  * bufsize bytes big.
174  *
175  * If the conversion fails, it returns NULL.
176  */
177 const char *
178 Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
179 {
180   const struct sockaddr_in *sa4;
181   const struct in_addr *ipaddr4;
182 #ifdef ENABLE_IPV6
183   const struct sockaddr_in6 *sa6;
184   const struct in6_addr *ipaddr6;
185 #endif
186
187   switch (ai->ai_family) {
188     case AF_INET:
189       sa4 = (const void *)ai->ai_addr;
190       ipaddr4 = &sa4->sin_addr;
191       return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf,
192                             bufsize);
193 #ifdef ENABLE_IPV6
194     case AF_INET6:
195       sa6 = (const void *)ai->ai_addr;
196       ipaddr6 = &sa6->sin6_addr;
197       return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf,
198                             bufsize);
199 #endif
200     default:
201       break;
202   }
203   return NULL;
204 }
205
206 /*
207  * Return a hostcache id string for the providing host + port, to be used by
208  * the DNS caching.
209  */
210 static char *
211 create_hostcache_id(const char *server, int port)
212 {
213   /* create and return the new allocated entry */
214   return aprintf("%s:%d", server, port);
215 }
216
217 struct hostcache_prune_data {
218   long cache_timeout;
219   time_t now;
220 };
221
222 /*
223  * This function is set as a callback to be called for every entry in the DNS
224  * cache when we want to prune old unused entries.
225  *
226  * Returning non-zero means remove the entry, return 0 to keep it in the
227  * cache.
228  */
229 static int
230 hostcache_timestamp_remove(void *datap, void *hc)
231 {
232   struct hostcache_prune_data *data =
233     (struct hostcache_prune_data *) datap;
234   struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
235
236   return (data->now - c->timestamp >= data->cache_timeout);
237 }
238
239 /*
240  * Prune the DNS cache. This assumes that a lock has already been taken.
241  */
242 static void
243 hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now)
244 {
245   struct hostcache_prune_data user;
246
247   user.cache_timeout = cache_timeout;
248   user.now = now;
249
250   Curl_hash_clean_with_criterium(hostcache,
251                                  (void *) &user,
252                                  hostcache_timestamp_remove);
253 }
254
255 /*
256  * Library-wide function for pruning the DNS cache. This function takes and
257  * returns the appropriate locks.
258  */
259 void Curl_hostcache_prune(struct SessionHandle *data)
260 {
261   time_t now;
262
263   if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
264     /* cache forever means never prune, and NULL hostcache means
265        we can't do it */
266     return;
267
268   if(data->share)
269     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
270
271   time(&now);
272
273   /* Remove outdated and unused entries from the hostcache */
274   hostcache_prune(data->dns.hostcache,
275                   data->set.dns_cache_timeout,
276                   now);
277
278   if(data->share)
279     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
280 }
281
282 /*
283  * Check if the entry should be pruned. Assumes a locked cache.
284  */
285 static int
286 remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns)
287 {
288   struct hostcache_prune_data user;
289
290   if( !dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
291     /* cache forever means never prune, and NULL hostcache means
292        we can't do it */
293     return 0;
294
295   time(&user.now);
296   user.cache_timeout = data->set.dns_cache_timeout;
297
298   if( !hostcache_timestamp_remove(&user,dns) )
299     return 0;
300
301   Curl_hash_clean_with_criterium(data->dns.hostcache,
302                                  (void *) &user,
303                                  hostcache_timestamp_remove);
304
305   return 1;
306 }
307
308
309 #ifdef HAVE_SIGSETJMP
310 /* Beware this is a global and unique instance. This is used to store the
311    return address that we can jump back to from inside a signal handler. This
312    is not thread-safe stuff. */
313 sigjmp_buf curl_jmpenv;
314 #endif
315
316
317 /*
318  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
319  *
320  * When calling Curl_resolv() has resulted in a response with a returned
321  * address, we call this function to store the information in the dns
322  * cache etc
323  *
324  * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
325  */
326 struct Curl_dns_entry *
327 Curl_cache_addr(struct SessionHandle *data,
328                 Curl_addrinfo *addr,
329                 const char *hostname,
330                 int port)
331 {
332   char *entry_id;
333   size_t entry_len;
334   struct Curl_dns_entry *dns;
335   struct Curl_dns_entry *dns2;
336
337   /* Create an entry id, based upon the hostname and port */
338   entry_id = create_hostcache_id(hostname, port);
339   /* If we can't create the entry id, fail */
340   if(!entry_id)
341     return NULL;
342   entry_len = strlen(entry_id);
343
344   /* Create a new cache entry */
345   dns = calloc(1, sizeof(struct Curl_dns_entry));
346   if(!dns) {
347     free(entry_id);
348     return NULL;
349   }
350
351   dns->inuse = 0;   /* init to not used */
352   dns->addr = addr; /* this is the address(es) */
353   time(&dns->timestamp);
354   if(dns->timestamp == 0)
355     dns->timestamp = 1;   /* zero indicates that entry isn't in hash table */
356
357   /* Store the resolved data in our DNS cache. */
358   dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
359                        (void *)dns);
360   if(!dns2) {
361     free(dns);
362     free(entry_id);
363     return NULL;
364   }
365
366   dns = dns2;
367   dns->inuse++;         /* mark entry as in-use */
368
369   /* free the allocated entry_id again */
370   free(entry_id);
371
372   return dns;
373 }
374
375 /*
376  * Curl_resolv() is the main name resolve function within libcurl. It resolves
377  * a name and returns a pointer to the entry in the 'entry' argument (if one
378  * is provided). This function might return immediately if we're using asynch
379  * resolves. See the return codes.
380  *
381  * The cache entry we return will get its 'inuse' counter increased when this
382  * function is used. You MUST call Curl_resolv_unlock() later (when you're
383  * done using this struct) to decrease the counter again.
384  *
385  * In debug mode, we specifically test for an interface name "LocalHost"
386  * and resolve "localhost" instead as a means to permit test cases
387  * to connect to a local test server with any host name.
388  *
389  * Return codes:
390  *
391  * CURLRESOLV_ERROR   (-1) = error, no pointer
392  * CURLRESOLV_RESOLVED (0) = OK, pointer provided
393  * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
394  */
395
396 int Curl_resolv(struct connectdata *conn,
397                 const char *hostname,
398                 int port,
399                 struct Curl_dns_entry **entry)
400 {
401   char *entry_id = NULL;
402   struct Curl_dns_entry *dns = NULL;
403   size_t entry_len;
404   struct SessionHandle *data = conn->data;
405   CURLcode result;
406   int rc = CURLRESOLV_ERROR; /* default to failure */
407
408   *entry = NULL;
409
410   /* Create an entry id, based upon the hostname and port */
411   entry_id = create_hostcache_id(hostname, port);
412   /* If we can't create the entry id, fail */
413   if(!entry_id)
414     return rc;
415
416   entry_len = strlen(entry_id);
417
418   if(data->share)
419     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
420
421   /* See if its already in our dns cache */
422   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
423
424   /* See whether the returned entry is stale. Done before we release lock */
425   if( remove_entry_if_stale(data, dns) )
426     dns = NULL; /* the memory deallocation is being handled by the hash */
427
428   if(dns) {
429     dns->inuse++; /* we use it! */
430     rc = CURLRESOLV_RESOLVED;
431   }
432
433   if(data->share)
434     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
435
436   /* free the allocated entry_id again */
437   free(entry_id);
438
439   if(!dns) {
440     /* The entry was not in the cache. Resolve it to IP address */
441
442     Curl_addrinfo *addr;
443     int respwait;
444
445     /* Check what IP specifics the app has requested and if we can provide it.
446      * If not, bail out. */
447     if(!Curl_ipvalid(data))
448       return CURLRESOLV_ERROR;
449
450     /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
451        non-zero value indicating that we need to wait for the response to the
452        resolve call */
453     addr = Curl_getaddrinfo(conn,
454 #ifdef DEBUGBUILD
455                             (data->set.str[STRING_DEVICE]
456                              && !strcmp(data->set.str[STRING_DEVICE],
457                                         "LocalHost"))?"localhost":
458 #endif
459                             hostname, port, &respwait);
460
461     if(!addr) {
462       if(respwait) {
463         /* the response to our resolve call will come asynchronously at
464            a later time, good or bad */
465         /* First, check that we haven't received the info by now */
466         result = Curl_is_resolved(conn, &dns);
467         if(result) /* error detected */
468           return CURLRESOLV_ERROR;
469         if(dns)
470           rc = CURLRESOLV_RESOLVED; /* pointer provided */
471         else
472           rc = CURLRESOLV_PENDING; /* no info yet */
473       }
474     }
475     else {
476       if(data->share)
477         Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
478
479       /* we got a response, store it in the cache */
480       dns = Curl_cache_addr(data, addr, hostname, port);
481
482       if(data->share)
483         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
484
485       if(!dns)
486         /* returned failure, bail out nicely */
487         Curl_freeaddrinfo(addr);
488       else
489         rc = CURLRESOLV_RESOLVED;
490     }
491   }
492
493   *entry = dns;
494
495   return rc;
496 }
497
498 #ifdef USE_ALARM_TIMEOUT
499 /*
500  * This signal handler jumps back into the main libcurl code and continues
501  * execution.  This effectively causes the remainder of the application to run
502  * within a signal handler which is nonportable and could lead to problems.
503  */
504 static
505 RETSIGTYPE alarmfunc(int sig)
506 {
507   /* this is for "-ansi -Wall -pedantic" to stop complaining!   (rabe) */
508   (void)sig;
509   siglongjmp(curl_jmpenv, 1);
510   return;
511 }
512 #endif /* USE_ALARM_TIMEOUT */
513
514 /*
515  * Curl_resolv_timeout() is the same as Curl_resolv() but specifies a
516  * timeout.  This function might return immediately if we're using asynch
517  * resolves. See the return codes.
518  *
519  * The cache entry we return will get its 'inuse' counter increased when this
520  * function is used. You MUST call Curl_resolv_unlock() later (when you're
521  * done using this struct) to decrease the counter again.
522  *
523  * If built with a synchronous resolver and use of signals is not
524  * disabled by the application, then a nonzero timeout will cause a
525  * timeout after the specified number of milliseconds. Otherwise, timeout
526  * is ignored.
527  *
528  * Return codes:
529  *
530  * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired
531  * CURLRESOLV_ERROR   (-1) = error, no pointer
532  * CURLRESOLV_RESOLVED (0) = OK, pointer provided
533  * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
534  */
535
536 int Curl_resolv_timeout(struct connectdata *conn,
537                         const char *hostname,
538                         int port,
539                         struct Curl_dns_entry **entry,
540                         long timeoutms)
541 {
542 #ifdef USE_ALARM_TIMEOUT
543 #ifdef HAVE_SIGACTION
544   struct sigaction keep_sigact;   /* store the old struct here */
545   bool keep_copysig=FALSE;        /* did copy it? */
546   struct sigaction sigact;
547 #else
548 #ifdef HAVE_SIGNAL
549   void (*keep_sigact)(int);       /* store the old handler here */
550 #endif /* HAVE_SIGNAL */
551 #endif /* HAVE_SIGACTION */
552   volatile long timeout;
553   unsigned int prev_alarm=0;
554   struct SessionHandle *data = conn->data;
555 #endif /* USE_ALARM_TIMEOUT */
556   int rc;
557
558   *entry = NULL;
559
560 #ifdef USE_ALARM_TIMEOUT
561   if (data->set.no_signal)
562     /* Ignore the timeout when signals are disabled */
563     timeout = 0;
564   else
565     timeout = timeoutms;
566
567   if(timeout && timeout < 1000)
568     /* The alarm() function only provides integer second resolution, so if
569        we want to wait less than one second we must bail out already now. */
570     return CURLRESOLV_TIMEDOUT;
571
572   if (timeout > 0) {
573     /*************************************************************
574      * Set signal handler to catch SIGALRM
575      * Store the old value to be able to set it back later!
576      *************************************************************/
577 #ifdef HAVE_SIGACTION
578     sigaction(SIGALRM, NULL, &sigact);
579     keep_sigact = sigact;
580     keep_copysig = TRUE; /* yes, we have a copy */
581     sigact.sa_handler = alarmfunc;
582 #ifdef SA_RESTART
583     /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
584     sigact.sa_flags &= ~SA_RESTART;
585 #endif
586     /* now set the new struct */
587     sigaction(SIGALRM, &sigact, NULL);
588 #else /* HAVE_SIGACTION */
589     /* no sigaction(), revert to the much lamer signal() */
590 #ifdef HAVE_SIGNAL
591     keep_sigact = signal(SIGALRM, alarmfunc);
592 #endif
593 #endif /* HAVE_SIGACTION */
594
595     /* alarm() makes a signal get sent when the timeout fires off, and that
596        will abort system calls */
597     prev_alarm = alarm((unsigned int) (timeout/1000L));
598
599     /* This allows us to time-out from the name resolver, as the timeout
600        will generate a signal and we will siglongjmp() from that here.
601        This technique has problems (see alarmfunc).
602        This should be the last thing we do before calling Curl_resolv(),
603        as otherwise we'd have to worry about variables that get modified
604        before we invoke Curl_resolv() (and thus use "volatile"). */
605     if(sigsetjmp(curl_jmpenv, 1)) {
606       /* this is coming from a siglongjmp() after an alarm signal */
607       failf(data, "name lookup timed out");
608       rc = CURLRESOLV_ERROR;
609       goto clean_up;
610     }
611   }
612
613 #else
614 #ifndef CURLRES_ASYNCH
615   if(timeoutms)
616     infof(conn->data, "timeout on name lookup is not supported\n");
617 #else
618   (void)timeoutms; /* timeoutms not used with an async resolver */
619 #endif
620 #endif /* USE_ALARM_TIMEOUT */
621
622   /* Perform the actual name resolution. This might be interrupted by an
623    * alarm if it takes too long.
624    */
625   rc = Curl_resolv(conn, hostname, port, entry);
626
627 clean_up:
628
629 #ifdef USE_ALARM_TIMEOUT
630   if (timeout > 0) {
631
632 #ifdef HAVE_SIGACTION
633     if(keep_copysig) {
634       /* we got a struct as it looked before, now put that one back nice
635          and clean */
636       sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
637     }
638 #else
639 #ifdef HAVE_SIGNAL
640     /* restore the previous SIGALRM handler */
641     signal(SIGALRM, keep_sigact);
642 #endif
643 #endif /* HAVE_SIGACTION */
644
645     /* switch back the alarm() to either zero or to what it was before minus
646        the time we spent until now! */
647     if(prev_alarm) {
648       /* there was an alarm() set before us, now put it back */
649       unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
650
651       /* the alarm period is counted in even number of seconds */
652       unsigned long alarm_set = prev_alarm - elapsed_ms/1000;
653
654       if(!alarm_set ||
655          ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
656         /* if the alarm time-left reached zero or turned "negative" (counted
657            with unsigned values), we should fire off a SIGALRM here, but we
658            won't, and zero would be to switch it off so we never set it to
659            less than 1! */
660         alarm(1);
661         rc = CURLRESOLV_TIMEDOUT;
662         failf(data, "Previous alarm fired off!");
663       }
664       else
665         alarm((unsigned int)alarm_set);
666     }
667     else
668       alarm(0); /* just shut it off */
669   }
670 #endif /* USE_ALARM_TIMEOUT */
671
672   return rc;
673 }
674
675 /*
676  * Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
677  * made, the struct may be destroyed due to pruning. It is important that only
678  * one unlock is made for each Curl_resolv() call.
679  */
680 void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
681 {
682   DEBUGASSERT(dns && (dns->inuse>0));
683
684   if(data->share)
685     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
686
687   dns->inuse--;
688   /* only free if nobody is using AND it is not in hostcache (timestamp ==
689      0) */
690   if (dns->inuse == 0 && dns->timestamp == 0) {
691     Curl_freeaddrinfo(dns->addr);
692     free(dns);
693   }
694
695   if(data->share)
696     Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
697 }
698
699 /*
700  * File-internal: free a cache dns entry.
701  */
702 static void freednsentry(void *freethis)
703 {
704   struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
705
706   /* mark the entry as not in hostcache */
707   p->timestamp = 0;
708   if (p->inuse == 0) {
709     Curl_freeaddrinfo(p->addr);
710     free(p);
711   }
712 }
713
714 /*
715  * Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
716  */
717 struct curl_hash *Curl_mk_dnscache(void)
718 {
719   return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry);
720 }
721
722