File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / hostip6.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: /***************************************************************************
    2:  *                                  _   _ ____  _
    3:  *  Project                     ___| | | |  _ \| |
    4:  *                             / __| | | | |_) | |
    5:  *                            | (__| |_| |  _ <| |___
    6:  *                             \___|\___/|_| \_\_____|
    7:  *
    8:  * Copyright (C) 1998 - 2020, 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 https://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 "curl_setup.h"
   24: 
   25: /***********************************************************************
   26:  * Only for IPv6-enabled builds
   27:  **********************************************************************/
   28: #ifdef CURLRES_IPV6
   29: 
   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 __VMS
   40: #include <in.h>
   41: #include <inet.h>
   42: #endif
   43: 
   44: #ifdef HAVE_PROCESS_H
   45: #include <process.h>
   46: #endif
   47: 
   48: #include "urldata.h"
   49: #include "sendf.h"
   50: #include "hostip.h"
   51: #include "hash.h"
   52: #include "share.h"
   53: #include "strerror.h"
   54: #include "url.h"
   55: #include "inet_pton.h"
   56: #include "connect.h"
   57: /* The last 3 #include files should be in this order */
   58: #include "curl_printf.h"
   59: #include "curl_memory.h"
   60: #include "memdebug.h"
   61: 
   62: /*
   63:  * Curl_ipv6works() returns TRUE if IPv6 seems to work.
   64:  */
   65: bool Curl_ipv6works(struct connectdata *conn)
   66: {
   67:   if(conn) {
   68:     /* the nature of most system is that IPv6 status doesn't come and go
   69:        during a program's lifetime so we only probe the first time and then we
   70:        have the info kept for fast re-use */
   71:     DEBUGASSERT(conn);
   72:     DEBUGASSERT(conn->data);
   73:     DEBUGASSERT(conn->data->multi);
   74:     return conn->data->multi->ipv6_works;
   75:   }
   76:   else {
   77:     int ipv6_works = -1;
   78:     /* probe to see if we have a working IPv6 stack */
   79:     curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
   80:     if(s == CURL_SOCKET_BAD)
   81:       /* an IPv6 address was requested but we can't get/use one */
   82:       ipv6_works = 0;
   83:     else {
   84:       ipv6_works = 1;
   85:       Curl_closesocket(NULL, s);
   86:     }
   87:     return (ipv6_works>0)?TRUE:FALSE;
   88:   }
   89: }
   90: 
   91: /*
   92:  * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
   93:  * been set and returns TRUE if they are OK.
   94:  */
   95: bool Curl_ipvalid(struct connectdata *conn)
   96: {
   97:   if(conn->ip_version == CURL_IPRESOLVE_V6)
   98:     return Curl_ipv6works(conn);
   99: 
  100:   return TRUE;
  101: }
  102: 
  103: #if defined(CURLRES_SYNCH)
  104: 
  105: #ifdef DEBUG_ADDRINFO
  106: static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
  107: {
  108:   printf("dump_addrinfo:\n");
  109:   for(; ai; ai = ai->ai_next) {
  110:     char buf[INET6_ADDRSTRLEN];
  111:     printf("    fam %2d, CNAME %s, ",
  112:            ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
  113:     if(Curl_printable_address(ai, buf, sizeof(buf)))
  114:       printf("%s\n", buf);
  115:     else {
  116:       char buffer[STRERROR_LEN];
  117:       printf("failed; %s\n",
  118:              Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
  119:     }
  120:   }
  121: }
  122: #else
  123: #define dump_addrinfo(x,y) Curl_nop_stmt
  124: #endif
  125: 
  126: /*
  127:  * Curl_getaddrinfo() when built IPv6-enabled (non-threading and
  128:  * non-ares version).
  129:  *
  130:  * Returns name information about the given hostname and port number. If
  131:  * successful, the 'addrinfo' is returned and the forth argument will point to
  132:  * memory we need to free after use. That memory *MUST* be freed with
  133:  * Curl_freeaddrinfo(), nothing else.
  134:  */
  135: Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
  136:                                 const char *hostname,
  137:                                 int port,
  138:                                 int *waitp)
  139: {
  140:   struct addrinfo hints;
  141:   Curl_addrinfo *res;
  142:   int error;
  143:   char sbuf[12];
  144:   char *sbufptr = NULL;
  145: #ifndef USE_RESOLVE_ON_IPS
  146:   char addrbuf[128];
  147: #endif
  148:   int pf;
  149: #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
  150:   struct Curl_easy *data = conn->data;
  151: #endif
  152: 
  153:   *waitp = 0; /* synchronous response only */
  154: 
  155:   /* Check if a limited name resolve has been requested */
  156:   switch(conn->ip_version) {
  157:   case CURL_IPRESOLVE_V4:
  158:     pf = PF_INET;
  159:     break;
  160:   case CURL_IPRESOLVE_V6:
  161:     pf = PF_INET6;
  162:     break;
  163:   default:
  164:     pf = PF_UNSPEC;
  165:     break;
  166:   }
  167: 
  168:   if((pf != PF_INET) && !Curl_ipv6works(conn))
  169:     /* The stack seems to be a non-IPv6 one */
  170:     pf = PF_INET;
  171: 
  172:   memset(&hints, 0, sizeof(hints));
  173:   hints.ai_family = pf;
  174:   hints.ai_socktype = (conn->transport == TRNSPRT_TCP) ?
  175:     SOCK_STREAM : SOCK_DGRAM;
  176: 
  177: #ifndef USE_RESOLVE_ON_IPS
  178:   /*
  179:    * The AI_NUMERICHOST must not be set to get synthesized IPv6 address from
  180:    * an IPv4 address on iOS and Mac OS X.
  181:    */
  182:   if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
  183:      (1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {
  184:     /* the given address is numerical only, prevent a reverse lookup */
  185:     hints.ai_flags = AI_NUMERICHOST;
  186:   }
  187: #endif
  188: 
  189:   if(port) {
  190:     msnprintf(sbuf, sizeof(sbuf), "%d", port);
  191:     sbufptr = sbuf;
  192:   }
  193: 
  194:   error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
  195:   if(error) {
  196:     infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
  197:     return NULL;
  198:   }
  199: 
  200:   if(port) {
  201:     Curl_addrinfo_set_port(res, port);
  202:   }
  203: 
  204:   dump_addrinfo(conn, res);
  205: 
  206:   return res;
  207: }
  208: #endif /* CURLRES_SYNCH */
  209: 
  210: #endif /* CURLRES_IPV6 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>