root/ext/standard/dns_win32.c

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

DEFINITIONS

This source file includes following definitions.
  1. PHP_FUNCTION
  2. PHP_FUNCTION
  3. php_parserr
  4. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 2008-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Pierre A. Joye <pierre@php.net>                             |
  16    +----------------------------------------------------------------------+
  17  */
  18 
  19 #include "php.h"
  20 
  21 #include <windows.h>
  22 #include <Winbase.h >
  23 #include <Windns.h>
  24 
  25 #include "php_dns.h"
  26 
  27 #define PHP_DNS_NUM_TYPES       12      /* Number of DNS Types Supported by PHP currently */
  28 
  29 #define PHP_DNS_A      0x00000001
  30 #define PHP_DNS_NS     0x00000002
  31 #define PHP_DNS_CNAME  0x00000010
  32 #define PHP_DNS_SOA    0x00000020
  33 #define PHP_DNS_PTR    0x00000800
  34 #define PHP_DNS_HINFO  0x00001000
  35 #define PHP_DNS_MX     0x00004000
  36 #define PHP_DNS_TXT    0x00008000
  37 #define PHP_DNS_A6     0x01000000
  38 #define PHP_DNS_SRV    0x02000000
  39 #define PHP_DNS_NAPTR  0x04000000
  40 #define PHP_DNS_AAAA   0x08000000
  41 #define PHP_DNS_ANY    0x10000000
  42 #define PHP_DNS_ALL    (PHP_DNS_A|PHP_DNS_NS|PHP_DNS_CNAME|PHP_DNS_SOA|PHP_DNS_PTR|PHP_DNS_HINFO|PHP_DNS_MX|PHP_DNS_TXT|PHP_DNS_A6|PHP_DNS_SRV|PHP_DNS_NAPTR|PHP_DNS_AAAA)
  43 
  44 PHP_FUNCTION(dns_get_mx) /* {{{ */
  45 {
  46         char *hostname;
  47         int hostname_len;
  48         zval *mx_list, *weight_list = NULL;
  49 
  50         DNS_STATUS      status;                 /* Return value of DnsQuery_A() function */
  51         PDNS_RECORD     pResult, pRec;          /* Pointer to DNS_RECORD structure */
  52 
  53         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) {
  54                 return;
  55         }
  56 
  57         status = DnsQuery_A(hostname, DNS_TYPE_MX, DNS_QUERY_STANDARD, NULL, &pResult, NULL);
  58 
  59         if (status) {
  60                 RETURN_FALSE;
  61         }
  62 
  63         zval_dtor(mx_list);
  64         array_init(mx_list);
  65 
  66         if (weight_list) {
  67                 zval_dtor(weight_list);
  68                 array_init(weight_list);
  69         }
  70 
  71         for (pRec = pResult; pRec; pRec = pRec->pNext) {
  72                 DNS_SRV_DATA *srv = &pRec->Data.Srv;
  73 
  74                 if (pRec->wType != DNS_TYPE_MX) {
  75                         continue;
  76                 }
  77 
  78                 add_next_index_string(mx_list, pRec->Data.MX.pNameExchange, 1);
  79                 if (weight_list) {
  80                         add_next_index_long(weight_list, srv->wPriority);
  81                 }
  82         }
  83 
  84         /* Free memory allocated for DNS records. */
  85         DnsRecordListFree(pResult, DnsFreeRecordListDeep);
  86 
  87         RETURN_TRUE;
  88 }
  89 /* }}} */
  90 
  91 /* {{{ proto bool dns_check_record(string host [, string type])
  92    Check DNS records corresponding to a given Internet host name or IP address */
  93 PHP_FUNCTION(dns_check_record)
  94 {
  95         char *hostname, *rectype = NULL;
  96         int hostname_len, rectype_len = 0;
  97         int type = DNS_TYPE_MX;
  98 
  99         DNS_STATUS      status;                 /* Return value of DnsQuery_A() function */
 100         PDNS_RECORD     pResult;          /* Pointer to DNS_RECORD structure */
 101 
 102         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &hostname, &hostname_len, &rectype, &rectype_len) == FAILURE) {
 103                 return;
 104         }
 105 
 106         if (hostname_len == 0) {
 107                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host cannot be empty");
 108                 RETURN_FALSE;
 109         }
 110 
 111         if (rectype) {
 112                      if (!strcasecmp("A",     rectype)) type = DNS_TYPE_A;
 113                 else if (!strcasecmp("NS",    rectype)) type = DNS_TYPE_NS;
 114                 else if (!strcasecmp("MX",    rectype)) type = DNS_TYPE_MX;
 115                 else if (!strcasecmp("PTR",   rectype)) type = DNS_TYPE_PTR;
 116                 else if (!strcasecmp("ANY",   rectype)) type = DNS_TYPE_ANY;
 117                 else if (!strcasecmp("SOA",   rectype)) type = DNS_TYPE_SOA;
 118                 else if (!strcasecmp("TXT",   rectype)) type = DNS_TYPE_TEXT;
 119                 else if (!strcasecmp("CNAME", rectype)) type = DNS_TYPE_CNAME;
 120                 else if (!strcasecmp("AAAA",  rectype)) type = DNS_TYPE_AAAA;
 121                 else if (!strcasecmp("SRV",   rectype)) type = DNS_TYPE_SRV;
 122                 else if (!strcasecmp("NAPTR", rectype)) type = DNS_TYPE_NAPTR;
 123                 else if (!strcasecmp("A6",    rectype)) type = DNS_TYPE_A6;
 124                 else {
 125                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%s' not supported", rectype);
 126                         RETURN_FALSE;
 127                 }
 128         }
 129 
 130         status = DnsQuery_A(hostname, type, DNS_QUERY_STANDARD, NULL, &pResult, NULL);
 131 
 132         if (status) {
 133                 RETURN_FALSE;
 134         }
 135 
 136         RETURN_TRUE;
 137 }
 138 /* }}} */
 139 
 140 /* {{{ php_parserr */
 141 static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, int raw, zval **subarray)
 142 {
 143         int type;
 144         u_long ttl;
 145 
 146         type = pRec->wType;
 147         ttl = pRec->dwTtl;
 148 
 149         if (type_to_fetch != DNS_TYPE_ANY && type != type_to_fetch) {
 150                 return;
 151         }
 152 
 153         if (!store) {
 154                 return;
 155         }
 156 
 157         ALLOC_INIT_ZVAL(*subarray);
 158         array_init(*subarray);
 159 
 160         add_assoc_string(*subarray, "host", pRec->pName, 1);
 161         add_assoc_string(*subarray, "class", "IN", 1);
 162         add_assoc_long(*subarray, "ttl", ttl);
 163 
 164         if (raw) {
 165                 add_assoc_long(*subarray, "type", type);
 166                 add_assoc_stringl(*subarray, "data", (char*) &pRec->Data, (uint) pRec->wDataLength, 1);
 167                 return;
 168         }
 169 
 170         switch (type) {
 171                 case DNS_TYPE_A: {
 172                         IN_ADDR ipaddr;
 173                         ipaddr.S_un.S_addr = (pRec->Data.A.IpAddress);
 174                         add_assoc_string(*subarray, "type", "A", 1);
 175                         add_assoc_string(*subarray, "ip", inet_ntoa(ipaddr), 1);
 176                         break;
 177                 }
 178 
 179                 case DNS_TYPE_MX:
 180                         add_assoc_string(*subarray, "type", "MX", 1);
 181                         add_assoc_long(*subarray, "pri", pRec->Data.Srv.wPriority);
 182                         /* no break; */
 183 
 184                 case DNS_TYPE_CNAME:
 185                         if (type == DNS_TYPE_CNAME) {
 186                                 add_assoc_string(*subarray, "type", "CNAME", 1);
 187                         }
 188                         /* no break; */
 189 
 190                 case DNS_TYPE_NS:
 191                         if (type == DNS_TYPE_NS) {
 192                                 add_assoc_string(*subarray, "type", "NS", 1);
 193                         }
 194                         /* no break; */
 195 
 196                 case DNS_TYPE_PTR:
 197                         if (type == DNS_TYPE_PTR) {
 198                                 add_assoc_string(*subarray, "type", "PTR", 1);
 199                         }
 200                         add_assoc_string(*subarray, "target", pRec->Data.MX.pNameExchange, 1);
 201                         break;
 202 
 203                 /* Not available on windows, the query is possible but there is no DNS_HINFO_DATA structure */
 204                 case DNS_TYPE_HINFO:
 205                 case DNS_TYPE_TEXT:
 206                         {
 207                                 DWORD i = 0;
 208                                 DNS_TXT_DATA *data_txt = &pRec->Data.TXT;
 209                                 DWORD count = data_txt->dwStringCount;
 210                                 char *txt, *txt_dst;
 211                                 long txt_len = 0;
 212                                 zval *entries;
 213 
 214                                 add_assoc_string(*subarray, "type", "TXT", 1);
 215                                 
 216                                 ALLOC_INIT_ZVAL(entries);
 217                                 array_init(entries);
 218                                 
 219                                 for (i = 0; i < count; i++) {
 220                                         txt_len += strlen(data_txt->pStringArray[i]) + 1;
 221                                 }
 222 
 223                                 txt = ecalloc(txt_len * 2, 1);
 224                                 txt_dst = txt;
 225                                 for (i = 0; i < count; i++) {
 226                                         int len = strlen(data_txt->pStringArray[i]);
 227                                         memcpy(txt_dst, data_txt->pStringArray[i], len);
 228                                         add_next_index_stringl(entries, data_txt->pStringArray[i], len, 1);
 229                                         txt_dst += len;
 230                                 }
 231 
 232                                 add_assoc_string(*subarray, "txt", txt, 0);
 233                                 add_assoc_zval(*subarray, "entries", entries);
 234                         }
 235                         break;
 236 
 237                 case DNS_TYPE_SOA:
 238                         {
 239                                 DNS_SOA_DATA *data_soa = &pRec->Data.Soa;
 240 
 241                                 add_assoc_string(*subarray, "type", "SOA", 1);
 242 
 243                                 add_assoc_string(*subarray, "mname", data_soa->pNamePrimaryServer, 1);
 244                                 add_assoc_string(*subarray, "rname", data_soa->pNameAdministrator, 1);
 245                                 add_assoc_long(*subarray, "serial", data_soa->dwSerialNo);
 246                                 add_assoc_long(*subarray, "refresh", data_soa->dwRefresh);
 247                                 add_assoc_long(*subarray, "retry", data_soa->dwRetry);
 248                                 add_assoc_long(*subarray, "expire", data_soa->dwExpire);
 249                                 add_assoc_long(*subarray, "minimum-ttl", data_soa->dwDefaultTtl);
 250                         }
 251                         break;
 252 
 253                 case DNS_TYPE_AAAA:
 254                         {
 255                                 DNS_AAAA_DATA *data_aaaa = &pRec->Data.AAAA;
 256                                 char buf[sizeof("AAAA:AAAA:AAAA:AAAA:AAAA:AAAA:AAAA:AAAA")];
 257                                 char *tp = buf;
 258                                 int i;
 259                                 unsigned short out[8];
 260                                 int have_v6_break = 0, in_v6_break = 0;
 261 
 262                                 for (i = 0; i < 4; ++i) {
 263                                         DWORD chunk = data_aaaa->Ip6Address.IP6Dword[i];
 264                                         out[i * 2]     = htons(LOWORD(chunk));
 265                                         out[i * 2 + 1] = htons(HIWORD(chunk));
 266                                 }
 267 
 268                                 for(i=0; i < 8; i++) {
 269                                         if (out[i] != 0) {
 270                                                 if (tp > (u_char *)buf) {
 271                                                         in_v6_break = 0;
 272                                                         tp[0] = ':';
 273                                                         tp++;
 274                                                 }
 275                                                 tp += sprintf((char*)tp,"%x", out[i]);
 276                                         } else {
 277                                                 if (!have_v6_break) {
 278                                                         have_v6_break = 1;
 279                                                         in_v6_break = 1;
 280                                                         tp[0] = ':';
 281                                                         tp++;
 282                                                 } else if (!in_v6_break) {
 283                                                         tp[0] = ':';
 284                                                         tp++;
 285                                                         tp[0] = '0';
 286                                                         tp++;
 287                                                 }
 288                                         }
 289                                 }
 290 
 291                                 if (have_v6_break && in_v6_break) {
 292                                         tp[0] = ':';
 293                                         tp++;
 294                                 }
 295                                 tp[0] = '\0';
 296 
 297                                 add_assoc_string(*subarray, "type", "AAAA", 1);
 298                                 add_assoc_string(*subarray, "ipv6", buf, 1);
 299                         }
 300                         break;
 301 
 302 #if 0
 303                 /* Won't be implemented. A6 is deprecated. (Pierre) */
 304                 case DNS_TYPE_A6:
 305                         break;
 306 #endif
 307 
 308                 case DNS_TYPE_SRV:
 309                         {
 310                                 DNS_SRV_DATA *data_srv = &pRec->Data.Srv;
 311 
 312                                 add_assoc_string(*subarray, "type", "SRV", 1);
 313                                 add_assoc_long(*subarray, "pri", data_srv->wPriority);
 314                                 add_assoc_long(*subarray, "weight", data_srv->wWeight);
 315                                 add_assoc_long(*subarray, "port", data_srv->wPort);
 316                                 add_assoc_string(*subarray, "target", data_srv->pNameTarget, 1);
 317                         }
 318                         break;
 319 
 320 #if _MSC_VER >= 1500
 321                 case DNS_TYPE_NAPTR:
 322                         {
 323                                 DNS_NAPTR_DATA * data_naptr = &pRec->Data.Naptr;
 324 
 325                                 add_assoc_string(*subarray, "type", "NAPTR", 1);
 326                                 add_assoc_long(*subarray, "order", data_naptr->wOrder);
 327                                 add_assoc_long(*subarray, "pref", data_naptr->wPreference);
 328                                 add_assoc_string(*subarray, "flags", data_naptr->pFlags, 1);
 329                                 add_assoc_string(*subarray, "services", data_naptr->pService, 1);
 330                                 add_assoc_string(*subarray, "regex", data_naptr->pRegularExpression, 1);
 331                                 add_assoc_string(*subarray, "replacement", data_naptr->pReplacement, 1);
 332                         }
 333                         break;
 334 #endif
 335 
 336                 default:
 337                         /* unknown type */
 338                         zval_ptr_dtor(subarray);
 339                         *subarray = NULL;
 340                         return;
 341         }
 342 
 343 }
 344 /* }}} */
 345 
 346 /* {{{ proto array|false dns_get_record(string hostname [, int type[, array authns, array addtl]])
 347    Get any Resource Record corresponding to a given Internet host name */
 348 PHP_FUNCTION(dns_get_record)
 349 {
 350         char *hostname;
 351         int hostname_len;
 352         long type_param = PHP_DNS_ANY;
 353         zval *authns = NULL, *addtl = NULL;
 354         int type, type_to_fetch, first_query = 1, store_results = 1;
 355         zend_bool raw = 0;
 356 
 357         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz!z!b",
 358                         &hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
 359                 return;
 360         }
 361 
 362         if (authns) {
 363                 zval_dtor(authns);
 364                 array_init(authns);
 365         }
 366         if (addtl) {
 367                 zval_dtor(addtl);
 368                 array_init(addtl);
 369         }
 370 
 371         if (!raw) {
 372                 if ((type_param & ~PHP_DNS_ALL) && (type_param != PHP_DNS_ANY)) {
 373                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
 374                         RETURN_FALSE;
 375                 }
 376         } else {
 377                 if ((type_param < 1) || (type_param > 0xFFFF)) {
 378                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
 379                                 "Numeric DNS record type must be between 1 and 65535, '%ld' given", type_param);
 380                         RETURN_FALSE;
 381                 }
 382         }
 383 
 384         /* Initialize the return array */
 385         array_init(return_value);
 386 
 387         if (raw) {
 388                 type = -1;
 389         } else if (type_param == PHP_DNS_ANY) {
 390                 type = PHP_DNS_NUM_TYPES + 1;
 391         } else {
 392                 type = 0;
 393         }
 394 
 395         for ( ;
 396                 type < (addtl ? (PHP_DNS_NUM_TYPES + 2) : PHP_DNS_NUM_TYPES) || first_query;
 397                 type++
 398         ) {
 399                 DNS_STATUS      status;                 /* Return value of DnsQuery_A() function */
 400                 PDNS_RECORD     pResult, pRec;          /* Pointer to DNS_RECORD structure */
 401 
 402                 first_query = 0;
 403                 switch (type) {
 404                         case -1: /* raw */
 405                                 type_to_fetch = type_param;
 406                                 /* skip over the rest and go directly to additional records */
 407                                 type = PHP_DNS_NUM_TYPES - 1;
 408                                 break;
 409                         case 0:
 410                                 type_to_fetch = type_param&PHP_DNS_A     ? DNS_TYPE_A     : 0;
 411                                 break;
 412                         case 1:
 413                                 type_to_fetch = type_param&PHP_DNS_NS    ? DNS_TYPE_NS    : 0;
 414                                 break;
 415                         case 2:
 416                                 type_to_fetch = type_param&PHP_DNS_CNAME ? DNS_TYPE_CNAME : 0;
 417                                 break;
 418                         case 3:
 419                                 type_to_fetch = type_param&PHP_DNS_SOA   ? DNS_TYPE_SOA   : 0;
 420                                 break;
 421                         case 4:
 422                                 type_to_fetch = type_param&PHP_DNS_PTR   ? DNS_TYPE_PTR   : 0;
 423                                 break;
 424                         case 5:
 425                                 type_to_fetch = type_param&PHP_DNS_HINFO ? DNS_TYPE_HINFO : 0;
 426                                 break;
 427                         case 6:
 428                                 type_to_fetch = type_param&PHP_DNS_MX    ? DNS_TYPE_MX    : 0;
 429                                 break;
 430                         case 7:
 431                                 type_to_fetch = type_param&PHP_DNS_TXT   ? DNS_TYPE_TEXT   : 0;
 432                                 break;
 433                         case 8:
 434                                 type_to_fetch = type_param&PHP_DNS_AAAA  ? DNS_TYPE_AAAA  : 0;
 435                                 break;
 436                         case 9:
 437                                 type_to_fetch = type_param&PHP_DNS_SRV   ? DNS_TYPE_SRV   : 0;
 438                                 break;
 439                         case 10:
 440                                 type_to_fetch = type_param&PHP_DNS_NAPTR ? DNS_TYPE_NAPTR : 0;
 441                                 break;
 442                         case 11:
 443                                 type_to_fetch = type_param&PHP_DNS_A6    ? DNS_TYPE_A6 : 0;
 444                                 break;
 445                         case PHP_DNS_NUM_TYPES:
 446                                 store_results = 0;
 447                                 continue;
 448                         default:
 449                         case (PHP_DNS_NUM_TYPES + 1):
 450                                 type_to_fetch = DNS_TYPE_ANY;
 451                                 break;
 452                 }
 453 
 454                 if (type_to_fetch) {
 455                         status = DnsQuery_A(hostname, type_to_fetch, DNS_QUERY_STANDARD, NULL, &pResult, NULL);
 456 
 457                         if (status) {
 458                                 if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR) {
 459                                         continue;
 460                                 } else {
 461                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "DNS Query failed");
 462                                         zval_dtor(return_value);
 463                                         RETURN_FALSE;
 464                                 }
 465                         }
 466 
 467                         for (pRec = pResult; pRec; pRec = pRec->pNext) {
 468                                 DNS_SRV_DATA *srv = &pRec->Data.Srv;
 469                                 zval *retval = NULL;
 470 
 471                                 if (pRec->Flags.S.Section == DnsSectionAnswer) {
 472                                         php_parserr(pRec, type_to_fetch, store_results, raw, &retval);
 473                                         if (retval != NULL && store_results) {
 474                                                 add_next_index_zval(return_value, retval);
 475                                         }
 476                                 }
 477 
 478                                 if (authns && pRec->Flags.S.Section == DnsSectionAuthority) {
 479 
 480                                         php_parserr(pRec, type_to_fetch, 1, raw, &retval);
 481                                         if (retval != NULL) {
 482                                                 add_next_index_zval(authns, retval);
 483                                         }
 484                                 }
 485 
 486 /* Stupid typo in PSDK 6.1, WinDNS.h(1258)... */
 487 #ifndef DnsSectionAdditional
 488 # ifdef DnsSectionAddtional
 489 #  define DnsSectionAdditional DnsSectionAddtional
 490 # else
 491 # define DnsSectionAdditional 3
 492 # endif
 493 #endif
 494                                 if (addtl && pRec->Flags.S.Section == DnsSectionAdditional) {
 495                                         php_parserr(pRec, type_to_fetch, 1, raw, &retval);
 496                                         if (retval != NULL) {
 497                                                 add_next_index_zval(addtl, retval);
 498                                         }
 499                                 }
 500                         }
 501                         /* Free memory allocated for DNS records. */
 502                         DnsRecordListFree(pResult, DnsFreeRecordListDeep);
 503                 }
 504         }
 505 }
 506 /* }}} */

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