root/ext/sockets/sockaddr_conv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_set_inet6_addr
  2. php_set_inet_addr
  3. php_set_inet46_addr

   1 #include <php.h>
   2 #include <php_network.h>
   3 #include "php_sockets.h"
   4 
   5 #ifdef PHP_WIN32
   6 #include "windows_common.h"
   7 #else
   8 #include <netdb.h>
   9 #include <arpa/inet.h>
  10 #endif
  11 
  12 extern int php_string_to_if_index(const char *val, unsigned *out);
  13 
  14 #if HAVE_IPV6
  15 /* Sets addr by hostname, or by ip in string form (AF_INET6) */
  16 int php_set_inet6_addr(struct sockaddr_in6 *sin6, char *string, php_socket *php_sock) /* {{{ */
  17 {
  18         struct in6_addr tmp;
  19 #if HAVE_GETADDRINFO
  20         struct addrinfo hints;
  21         struct addrinfo *addrinfo = NULL;
  22 #endif
  23         char *scope = strchr(string, '%');
  24 
  25         if (inet_pton(AF_INET6, string, &tmp)) {
  26                 memcpy(&(sin6->sin6_addr.s6_addr), &(tmp.s6_addr), sizeof(struct in6_addr));
  27         } else {
  28 #if HAVE_GETADDRINFO
  29 
  30                 memset(&hints, 0, sizeof(struct addrinfo));
  31                 hints.ai_family = AF_INET6;
  32 #if HAVE_AI_V4MAPPED
  33                 hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
  34 #else
  35                 hints.ai_flags = AI_ADDRCONFIG;
  36 #endif
  37                 getaddrinfo(string, NULL, &hints, &addrinfo);
  38                 if (!addrinfo) {
  39 #ifdef PHP_WIN32
  40                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError());
  41 #else
  42                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno));
  43 #endif
  44                         return 0;
  45                 }
  46                 if (addrinfo->ai_family != PF_INET6 || addrinfo->ai_addrlen != sizeof(struct sockaddr_in6)) {
  47                         php_error_docref(NULL, E_WARNING, "Host lookup failed: Non AF_INET6 domain returned on AF_INET6 socket");
  48                         freeaddrinfo(addrinfo);
  49                         return 0;
  50                 }
  51 
  52                 memcpy(&(sin6->sin6_addr.s6_addr), ((struct sockaddr_in6*)(addrinfo->ai_addr))->sin6_addr.s6_addr, sizeof(struct in6_addr));
  53                 freeaddrinfo(addrinfo);
  54 
  55 #else
  56                 /* No IPv6 specific hostname resolution is available on this system? */
  57                 php_error_docref(NULL, E_WARNING, "Host lookup failed: getaddrinfo() not available on this system");
  58                 return 0;
  59 #endif
  60 
  61         }
  62 
  63         if (scope++) {
  64                 zend_long lval = 0;
  65                 double dval = 0;
  66                 unsigned scope_id = 0;
  67 
  68                 if (IS_LONG == is_numeric_string(scope, strlen(scope), &lval, &dval, 0)) {
  69                         if (lval > 0 && lval <= UINT_MAX) {
  70                                 scope_id = lval;
  71                         }
  72                 } else {
  73                         php_string_to_if_index(scope, &scope_id);
  74                 }
  75 
  76                 sin6->sin6_scope_id = scope_id;
  77         }
  78 
  79         return 1;
  80 }
  81 /* }}} */
  82 #endif
  83 
  84 /* Sets addr by hostname, or by ip in string form (AF_INET)  */
  85 int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *php_sock) /* {{{ */
  86 {
  87         struct in_addr tmp;
  88         struct hostent *host_entry;
  89 
  90         if (inet_aton(string, &tmp)) {
  91                 sin->sin_addr.s_addr = tmp.s_addr;
  92         } else {
  93                 if (strlen(string) > MAXFQDNLEN || ! (host_entry = gethostbyname(string))) {
  94                         /* Note: < -10000 indicates a host lookup error */
  95 #ifdef PHP_WIN32
  96                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError());
  97 #else
  98                         PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno));
  99 #endif
 100                         return 0;
 101                 }
 102                 if (host_entry->h_addrtype != AF_INET) {
 103                         php_error_docref(NULL, E_WARNING, "Host lookup failed: Non AF_INET domain returned on AF_INET socket");
 104                         return 0;
 105                 }
 106                 memcpy(&(sin->sin_addr.s_addr), host_entry->h_addr_list[0], host_entry->h_length);
 107         }
 108 
 109         return 1;
 110 }
 111 /* }}} */
 112 
 113 /* Sets addr by hostname or by ip in string form (AF_INET or AF_INET6,
 114  * depending on the socket) */
 115 int php_set_inet46_addr(php_sockaddr_storage *ss, socklen_t *ss_len, char *string, php_socket *php_sock) /* {{{ */
 116 {
 117         if (php_sock->type == AF_INET) {
 118                 struct sockaddr_in t = {0};
 119                 if (php_set_inet_addr(&t, string, php_sock)) {
 120                         memcpy(ss, &t, sizeof t);
 121                         ss->ss_family = AF_INET;
 122                         *ss_len = sizeof(t);
 123                         return 1;
 124                 }
 125         }
 126 #if HAVE_IPV6
 127         else if (php_sock->type == AF_INET6) {
 128                 struct sockaddr_in6 t = {0};
 129                 if (php_set_inet6_addr(&t, string, php_sock)) {
 130                         memcpy(ss, &t, sizeof t);
 131                         ss->ss_family = AF_INET6;
 132                         *ss_len = sizeof(t);
 133                         return 1;
 134                 }
 135         }
 136 #endif
 137         else {
 138                 php_error_docref(NULL, E_WARNING,
 139                         "IP address used in the context of an unexpected type of socket");
 140         }
 141         return 0;
 142 }

/* [<][>][^][v][top][bottom][index][help] */