File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard / dns_win32.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:57 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 2008-2009 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: /* }}} */

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