Annotation of embedaddon/curl/lib/hostip6.c, revision 1.1

1.1     ! misho       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>