src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c
changeset 58876 1a8d65e71a66
parent 58433 a7c95e2f8814
equal deleted inserted replaced
58875:8c0e8cff877f 58876:1a8d65e71a66
    33 #include "sysSocket.h"
    33 #include "sysSocket.h"
    34 
    34 
    35 #ifdef _WIN32
    35 #ifdef _WIN32
    36  #include <winsock2.h>
    36  #include <winsock2.h>
    37  #include <ws2tcpip.h>
    37  #include <ws2tcpip.h>
       
    38  #include <iphlpapi.h>
    38 #else
    39 #else
    39  #include <arpa/inet.h>
    40  #include <arpa/inet.h>
    40  #include <sys/socket.h>
    41  #include <sys/socket.h>
       
    42  #include <net/if.h>
    41 #endif
    43 #endif
    42 
    44 
    43 /*
    45 /*
    44  * The Socket Transport Library.
    46  * The Socket Transport Library.
    45  *
    47  *
   265                                     ? (((struct sockaddr_in*)sa)->sin_port)
   267                                     ? (((struct sockaddr_in*)sa)->sin_port)
   266                                     : (((struct sockaddr_in6*)sa)->sin6_port));
   268                                     : (((struct sockaddr_in6*)sa)->sin6_port));
   267 }
   269 }
   268 
   270 
   269 /*
   271 /*
       
   272  * Parses scope id.
       
   273  * Scope id is ulong on Windows, uint32 on unix, so returns long which can be cast to uint32.
       
   274  * On error sets last error and returns -1.
       
   275  */
       
   276 static long parseScopeId(const char *str) {
       
   277     // try to handle scope as interface name
       
   278     unsigned long scopeId = if_nametoindex(str);
       
   279     if (scopeId == 0) {
       
   280         // try to parse integer value
       
   281         char *end;
       
   282         scopeId = strtoul(str, &end, 10);
       
   283         if (*end != '\0') {
       
   284             setLastError(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "failed to parse scope");
       
   285             return -1;
       
   286         }
       
   287     }
       
   288     // ensure parsed value is in uint32 range
       
   289     if (scopeId > 0xFFFFFFFF) {
       
   290         setLastError(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "scope is out of range");
       
   291         return -1;
       
   292     }
       
   293     return (long)scopeId;
       
   294 }
       
   295 
       
   296 /*
       
   297  * Wrapper for dbgsysGetAddrInfo (getaddrinfo).
       
   298  * Handles enclosing square brackets and scopes.
       
   299  */
       
   300 static jdwpTransportError
       
   301 getAddrInfo(const char *hostname, size_t hostnameLen,
       
   302             const char *service,
       
   303             const struct addrinfo *hints,
       
   304             struct addrinfo **result)
       
   305 {
       
   306     int err = 0;
       
   307     char *buffer = NULL;
       
   308     long scopeId = 0;
       
   309 
       
   310     if (hostname != NULL) {
       
   311         char *scope = NULL;
       
   312         // skip surrounding
       
   313         if (hostnameLen > 2 && hostname[0] == '[' && hostname[hostnameLen - 1] == ']') {
       
   314             hostname++;
       
   315             hostnameLen -= 2;
       
   316         }
       
   317         buffer = (*callback->alloc)((int)hostnameLen + 1);
       
   318         if (buffer == NULL) {
       
   319             RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
       
   320         }
       
   321         memcpy(buffer, hostname, hostnameLen);
       
   322         buffer[hostnameLen] = '\0';
       
   323 
       
   324         scope = strchr(buffer, '%');
       
   325         if (scope != NULL) {
       
   326             // drop scope from the address
       
   327             *scope = '\0';
       
   328             // and parse the value
       
   329             scopeId = parseScopeId(scope + 1);
       
   330             if (scopeId < 0) {
       
   331                 (*callback->free)(buffer);
       
   332                 return JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT;
       
   333             }
       
   334         }
       
   335     }
       
   336 
       
   337     err = dbgsysGetAddrInfo(buffer, service, hints, result);
       
   338 
       
   339     if (buffer != NULL) {
       
   340         (*callback->free)(buffer);
       
   341     }
       
   342     if (err != 0) {
       
   343         setLastError(err, "getaddrinfo: failed to parse address");
       
   344         return JDWPTRANSPORT_ERROR_IO_ERROR;
       
   345     }
       
   346 
       
   347     if (scopeId > 0) {
       
   348         if ((*result)->ai_family != AF_INET6) {
       
   349             RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "IPv4 address cannot contain scope");
       
   350         }
       
   351 
       
   352         ((struct sockaddr_in6 *)((*result)->ai_addr))->sin6_scope_id = (uint32_t)scopeId;
       
   353     }
       
   354 
       
   355     return JDWPTRANSPORT_ERROR_NONE;
       
   356 }
       
   357 
       
   358 /*
   270  * Result must be released with dbgsysFreeAddrInfo.
   359  * Result must be released with dbgsysFreeAddrInfo.
   271  */
   360  */
   272 static jdwpTransportError
   361 static jdwpTransportError
   273 parseAddress(const char *address, struct addrinfo **result) {
   362 parseAddress(const char *address, struct addrinfo **result) {
   274     const char *colon;
   363     const char *colon;
   275     size_t hostLen;
   364     size_t hostnameLen;
   276     char *host = NULL;
       
   277     const char *port;
   365     const char *port;
   278     struct addrinfo hints;
   366     struct addrinfo hints;
   279     int res;
       
   280 
   367 
   281     *result = NULL;
   368     *result = NULL;
   282 
   369 
   283     /* check for host:port or port */
   370     /* check for host:port or port */
   284     colon = strrchr(address, ':');
   371     colon = strrchr(address, ':');
   293     hints.ai_family = allowOnlyIPv4 ? AF_INET : AF_UNSPEC;
   380     hints.ai_family = allowOnlyIPv4 ? AF_INET : AF_UNSPEC;
   294     hints.ai_socktype = SOCK_STREAM;
   381     hints.ai_socktype = SOCK_STREAM;
   295     hints.ai_protocol = IPPROTO_TCP;
   382     hints.ai_protocol = IPPROTO_TCP;
   296     hints.ai_flags = AI_NUMERICSERV;    // port must be a number
   383     hints.ai_flags = AI_NUMERICSERV;    // port must be a number
   297 
   384 
   298     hostLen = (colon == NULL ? 0 : colon - address);
   385     hostnameLen = (colon == NULL ? 0 : colon - address);
   299     if (hostLen == 0) {
   386     if (hostnameLen == 0) {
   300         /* no hostname - use localhost address (pass NULL to getaddrinfo) */
   387         /* no hostname - use localhost address (pass NULL to getaddrinfo) */
   301     } else  if (*address == '*' && hostLen == 1) {
   388         address = NULL;
       
   389     } else  if (*address == '*' && hostnameLen == 1) {
   302         /* *:port - listen on all interfaces
   390         /* *:port - listen on all interfaces
   303          * use IPv6 socket (to accept IPv6 and mapped IPv4),
   391          * use IPv6 socket (to accept IPv6 and mapped IPv4),
   304          * pass hostname == NULL to getaddrinfo.
   392          * pass hostname == NULL to getaddrinfo.
   305          */
   393          */
   306         hints.ai_family = allowOnlyIPv4 ? AF_INET : AF_INET6;
   394         hints.ai_family = allowOnlyIPv4 ? AF_INET : AF_INET6;
   307         hints.ai_flags |= AI_PASSIVE | (allowOnlyIPv4 ? 0 : AI_V4MAPPED | AI_ALL);
   395         hints.ai_flags |= AI_PASSIVE | (allowOnlyIPv4 ? 0 : AI_V4MAPPED | AI_ALL);
   308     } else {
   396         address = NULL;
   309         if (address[0] == '[' && colon[-1] == ']') {
   397     }
   310             address++;
   398 
   311             hostLen -= 2;
   399     return getAddrInfo(address, hostnameLen, port, &hints, result);
   312         }
       
   313         host = (*callback->alloc)((int)hostLen + 1);
       
   314         if (host == NULL) {
       
   315             RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");
       
   316         }
       
   317         strncpy(host, address, hostLen);
       
   318         host[hostLen] = '\0';
       
   319     }
       
   320 
       
   321     res = dbgsysGetAddrInfo(host, port, &hints, result);
       
   322     if (host != NULL) {
       
   323         (*callback->free)(host);
       
   324     }
       
   325     if (res != 0) {
       
   326         setLastError(res, "getaddrinfo: unknown host");
       
   327         return JDWPTRANSPORT_ERROR_IO_ERROR;
       
   328     }
       
   329 
       
   330     return JDWPTRANSPORT_ERROR_NONE;
       
   331 }
   400 }
   332 
   401 
   333 /*
   402 /*
   334  * Input is sockaddr just because all clients have it.
   403  * Input is sockaddr just because all clients have it.
   335  */
   404  */
   350  */
   419  */
   351 static jdwpTransportError
   420 static jdwpTransportError
   352 parseAllowedAddr(const char *buffer, struct in6_addr *result, int *isIPv4) {
   421 parseAllowedAddr(const char *buffer, struct in6_addr *result, int *isIPv4) {
   353     struct addrinfo hints;
   422     struct addrinfo hints;
   354     struct addrinfo *addrInfo = NULL;
   423     struct addrinfo *addrInfo = NULL;
   355     int err;
   424     jdwpTransportError err;
   356 
   425 
   357     /*
   426     /*
   358      * To parse both IPv4 and IPv6 need to specify AF_UNSPEC family
   427      * To parse both IPv4 and IPv6 need to specify AF_UNSPEC family
   359      * (with AF_INET6 IPv4 addresses are not parsed even with AI_V4MAPPED and AI_ALL flags).
   428      * (with AF_INET6 IPv4 addresses are not parsed even with AI_V4MAPPED and AI_ALL flags).
   360      */
   429      */
   362     hints.ai_family = AF_UNSPEC;            // IPv6 or mapped IPv4
   431     hints.ai_family = AF_UNSPEC;            // IPv6 or mapped IPv4
   363     hints.ai_socktype = SOCK_STREAM;
   432     hints.ai_socktype = SOCK_STREAM;
   364     hints.ai_protocol = IPPROTO_TCP;
   433     hints.ai_protocol = IPPROTO_TCP;
   365     hints.ai_flags = AI_NUMERICHOST;        // only numeric addresses, no resolution
   434     hints.ai_flags = AI_NUMERICHOST;        // only numeric addresses, no resolution
   366 
   435 
   367     err = dbgsysGetAddrInfo(buffer, NULL, &hints, &addrInfo);
   436     err = getAddrInfo(buffer, strlen(buffer), NULL, &hints, &addrInfo);
   368 
   437 
   369     if (err != 0) {
   438     if (err != JDWPTRANSPORT_ERROR_NONE) {
   370         setLastError(err, "getaddrinfo: failed to parse address");
   439         return err;
   371         return JDWPTRANSPORT_ERROR_IO_ERROR;
       
   372     }
   440     }
   373 
   441 
   374     if (addrInfo->ai_family == AF_INET6) {
   442     if (addrInfo->ai_family == AF_INET6) {
   375         memcpy(result, &(((struct sockaddr_in6 *)(addrInfo->ai_addr))->sin6_addr), sizeof(*result));
   443         memcpy(result, &(((struct sockaddr_in6 *)(addrInfo->ai_addr))->sin6_addr), sizeof(*result));
   376         *isIPv4 = 0;
   444         *isIPv4 = 0;
   842     if (timeout > 0) {
   910     if (timeout > 0) {
   843         dbgsysConfigureBlocking(socketFD, JNI_FALSE);
   911         dbgsysConfigureBlocking(socketFD, JNI_FALSE);
   844     }
   912     }
   845 
   913 
   846     err = dbgsysConnect(socketFD, ai->ai_addr, (socklen_t)ai->ai_addrlen);
   914     err = dbgsysConnect(socketFD, ai->ai_addr, (socklen_t)ai->ai_addrlen);
       
   915 
   847     if (err == DBG_EINPROGRESS && timeout > 0) {
   916     if (err == DBG_EINPROGRESS && timeout > 0) {
   848         err = dbgsysFinishConnect(socketFD, (long)timeout);
   917         err = dbgsysFinishConnect(socketFD, (long)timeout);
   849 
   918 
   850         if (err == DBG_ETIMEOUT) {
   919         if (err == DBG_ETIMEOUT) {
   851             dbgsysConfigureBlocking(socketFD, JNI_TRUE);
   920             dbgsysConfigureBlocking(socketFD, JNI_TRUE);