Annotation of embedaddon/php/ext/standard/dns_win32.c, revision 1.1

1.1     ! misho       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, 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:        switch (type) {
        !           162:                case DNS_TYPE_A: {
        !           163:                        IN_ADDR ipaddr;
        !           164:                        ipaddr.S_un.S_addr = (pRec->Data.A.IpAddress);
        !           165:                        add_assoc_string(*subarray, "type", "A", 1);
        !           166:                        add_assoc_string(*subarray, "ip", inet_ntoa(ipaddr), 1);
        !           167:                        break;
        !           168:                }
        !           169: 
        !           170:                case DNS_TYPE_MX:
        !           171:                        add_assoc_string(*subarray, "type", "MX", 1);
        !           172:                        add_assoc_long(*subarray, "pri", pRec->Data.Srv.wPriority);
        !           173:                        /* no break; */
        !           174: 
        !           175:                case DNS_TYPE_CNAME:
        !           176:                        if (type == DNS_TYPE_CNAME) {
        !           177:                                add_assoc_string(*subarray, "type", "CNAME", 1);
        !           178:                        }
        !           179:                        /* no break; */
        !           180: 
        !           181:                case DNS_TYPE_NS:
        !           182:                        if (type == DNS_TYPE_NS) {
        !           183:                                add_assoc_string(*subarray, "type", "NS", 1);
        !           184:                        }
        !           185:                        /* no break; */
        !           186: 
        !           187:                case DNS_TYPE_PTR:
        !           188:                        if (type == DNS_TYPE_PTR) {
        !           189:                                add_assoc_string(*subarray, "type", "PTR", 1);
        !           190:                        }
        !           191:                        add_assoc_string(*subarray, "target", pRec->Data.MX.pNameExchange, 1);
        !           192:                        break;
        !           193: 
        !           194:                /* Not available on windows, the query is possible but there is no DNS_HINFO_DATA structure */
        !           195:                case DNS_TYPE_HINFO:
        !           196:                case DNS_TYPE_TEXT:
        !           197:                        {
        !           198:                                DWORD i = 0;
        !           199:                                DNS_TXT_DATA *data_txt = &pRec->Data.TXT;
        !           200:                                DWORD count = data_txt->dwStringCount;
        !           201:                                char *txt, *txt_dst;
        !           202:                                long txt_len = 0;
        !           203:                                zval *entries;
        !           204: 
        !           205:                                add_assoc_string(*subarray, "type", "TXT", 1);
        !           206:                                
        !           207:                                ALLOC_INIT_ZVAL(entries);
        !           208:                                array_init(entries);
        !           209:                                
        !           210:                                for (i = 0; i < count; i++) {
        !           211:                                        txt_len += strlen(data_txt->pStringArray[i]) + 1;
        !           212:                                }
        !           213: 
        !           214:                                txt = ecalloc(txt_len * 2, 1);
        !           215:                                txt_dst = txt;
        !           216:                                for (i = 0; i < count; i++) {
        !           217:                                        int len = strlen(data_txt->pStringArray[i]);
        !           218:                                        memcpy(txt_dst, data_txt->pStringArray[i], len);
        !           219:                                        add_next_index_stringl(entries, data_txt->pStringArray[i], len, 1);
        !           220:                                        txt_dst += len;
        !           221:                                }
        !           222: 
        !           223:                                add_assoc_string(*subarray, "txt", txt, 0);
        !           224:                                add_assoc_zval(*subarray, "entries", entries);
        !           225:                        }
        !           226:                        break;
        !           227: 
        !           228:                case DNS_TYPE_SOA:
        !           229:                        {
        !           230:                                DNS_SOA_DATA *data_soa = &pRec->Data.Soa;
        !           231: 
        !           232:                                add_assoc_string(*subarray, "type", "SOA", 1);
        !           233: 
        !           234:                                add_assoc_string(*subarray, "mname", data_soa->pNamePrimaryServer, 1);
        !           235:                                add_assoc_string(*subarray, "rname", data_soa->pNameAdministrator, 1);
        !           236:                                add_assoc_long(*subarray, "serial", data_soa->dwSerialNo);
        !           237:                                add_assoc_long(*subarray, "refresh", data_soa->dwRefresh);
        !           238:                                add_assoc_long(*subarray, "retry", data_soa->dwRetry);
        !           239:                                add_assoc_long(*subarray, "expire", data_soa->dwExpire);
        !           240:                                add_assoc_long(*subarray, "minimum-ttl", data_soa->dwDefaultTtl);
        !           241:                        }
        !           242:                        break;
        !           243: 
        !           244:                case DNS_TYPE_AAAA:
        !           245:                        {
        !           246:                                DNS_AAAA_DATA *data_aaaa = &pRec->Data.AAAA;
        !           247:                                char buf[sizeof("AAAA:AAAA:AAAA:AAAA:AAAA:AAAA:AAAA:AAAA")];
        !           248:                                char *tp = buf;
        !           249:                                int i;
        !           250:                                unsigned short out[8];
        !           251:                                int have_v6_break = 0, in_v6_break = 0;
        !           252: 
        !           253:                                for (i = 0; i < 4; ++i) {
        !           254:                                        DWORD chunk = data_aaaa->Ip6Address.IP6Dword[i];
        !           255:                                        out[i * 2]     = htons(LOWORD(chunk));
        !           256:                                        out[i * 2 + 1] = htons(HIWORD(chunk));
        !           257:                                }
        !           258: 
        !           259:                                for(i=0; i < 8; i++) {
        !           260:                                        if (out[i] != 0) {
        !           261:                                                if (tp > (u_char *)buf) {
        !           262:                                                        in_v6_break = 0;
        !           263:                                                        tp[0] = ':';
        !           264:                                                        tp++;
        !           265:                                                }
        !           266:                                                tp += sprintf((char*)tp,"%x", out[i]);
        !           267:                                        } else {
        !           268:                                                if (!have_v6_break) {
        !           269:                                                        have_v6_break = 1;
        !           270:                                                        in_v6_break = 1;
        !           271:                                                        tp[0] = ':';
        !           272:                                                        tp++;
        !           273:                                                } else if (!in_v6_break) {
        !           274:                                                        tp[0] = ':';
        !           275:                                                        tp++;
        !           276:                                                        tp[0] = '0';
        !           277:                                                        tp++;
        !           278:                                                }
        !           279:                                        }
        !           280:                                }
        !           281: 
        !           282:                                if (have_v6_break && in_v6_break) {
        !           283:                                        tp[0] = ':';
        !           284:                                        tp++;
        !           285:                                }
        !           286:                                tp[0] = '\0';
        !           287: 
        !           288:                                add_assoc_string(*subarray, "type", "AAAA", 1);
        !           289:                                add_assoc_string(*subarray, "ipv6", buf, 1);
        !           290:                        }
        !           291:                        break;
        !           292: 
        !           293: #if 0
        !           294:                /* Won't be implemented. A6 is deprecated. (Pierre) */
        !           295:                case DNS_TYPE_A6:
        !           296:                        break;
        !           297: #endif
        !           298: 
        !           299:                case DNS_TYPE_SRV:
        !           300:                        {
        !           301:                                DNS_SRV_DATA *data_srv = &pRec->Data.Srv;
        !           302: 
        !           303:                                add_assoc_string(*subarray, "type", "SRV", 1);
        !           304:                                add_assoc_long(*subarray, "pri", data_srv->wPriority);
        !           305:                                add_assoc_long(*subarray, "weight", data_srv->wWeight);
        !           306:                                add_assoc_long(*subarray, "port", data_srv->wPort);
        !           307:                                add_assoc_string(*subarray, "target", data_srv->pNameTarget, 1);
        !           308:                        }
        !           309:                        break;
        !           310: 
        !           311:                case DNS_TYPE_NAPTR:
        !           312:                        {
        !           313: #if _MSC_VER >= 1500
        !           314:                                DNS_NAPTR_DATA * data_naptr = &pRec->Data.Naptr;
        !           315: 
        !           316:                                add_assoc_string(*subarray, "type", "NAPTR", 1);
        !           317:                                add_assoc_long(*subarray, "order", data_naptr->wOrder);
        !           318:                                add_assoc_long(*subarray, "pref", data_naptr->wPreference);
        !           319:                                add_assoc_string(*subarray, "flags", data_naptr->pFlags, 1);
        !           320:                                add_assoc_string(*subarray, "services", data_naptr->pService, 1);
        !           321:                                add_assoc_string(*subarray, "regex", data_naptr->pRegularExpression, 1);
        !           322:                                add_assoc_string(*subarray, "replacement", data_naptr->pReplacement, 1);
        !           323: #endif
        !           324:                        }
        !           325:                        break;
        !           326: 
        !           327:                default:
        !           328:                        break;
        !           329:        }
        !           330: 
        !           331:        add_assoc_string(*subarray, "class", "IN", 1);
        !           332:        add_assoc_long(*subarray, "ttl", ttl);
        !           333: }
        !           334: /* }}} */
        !           335: 
        !           336: /* {{{ proto array|false dns_get_record(string hostname [, int type[, array authns, array addtl]])
        !           337:    Get any Resource Record corresponding to a given Internet host name */
        !           338: PHP_FUNCTION(dns_get_record)
        !           339: {
        !           340:        char *hostname;
        !           341:        int hostname_len;
        !           342:        long type_param = PHP_DNS_ANY;
        !           343:        zval *authns = NULL, *addtl = NULL;
        !           344:        int type, type_to_fetch, first_query = 1, store_results = 1;
        !           345: 
        !           346:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lzz", &hostname, &hostname_len, &type_param, &authns, &addtl) == FAILURE) {
        !           347:                return;
        !           348:        }
        !           349: 
        !           350:        if (authns) {
        !           351:                zval_dtor(authns);
        !           352:                array_init(authns);
        !           353:        }
        !           354:        if (addtl) {
        !           355:                zval_dtor(addtl);
        !           356:                array_init(addtl);
        !           357:        }
        !           358: 
        !           359:        if (type_param & ~PHP_DNS_ALL && type_param != PHP_DNS_ANY) {
        !           360:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
        !           361:                RETURN_FALSE;
        !           362:        }
        !           363: 
        !           364:        /* Initialize the return array */
        !           365:        array_init(return_value);
        !           366: 
        !           367:        for (type = (type_param == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0);
        !           368:                type < (addtl ? (PHP_DNS_NUM_TYPES + 2) : PHP_DNS_NUM_TYPES) || first_query;
        !           369:                type++
        !           370:        ) {
        !           371:                DNS_STATUS      status;                 /* Return value of DnsQuery_A() function */
        !           372:                PDNS_RECORD     pResult, pRec;          /* Pointer to DNS_RECORD structure */
        !           373: 
        !           374:                first_query = 0;
        !           375:                switch (type) {
        !           376:                        case 0:
        !           377:                                type_to_fetch = type_param&PHP_DNS_A     ? DNS_TYPE_A     : 0;
        !           378:                                break;
        !           379:                        case 1:
        !           380:                                type_to_fetch = type_param&PHP_DNS_NS    ? DNS_TYPE_NS    : 0;
        !           381:                                break;
        !           382:                        case 2:
        !           383:                                type_to_fetch = type_param&PHP_DNS_CNAME ? DNS_TYPE_CNAME : 0;
        !           384:                                break;
        !           385:                        case 3:
        !           386:                                type_to_fetch = type_param&PHP_DNS_SOA   ? DNS_TYPE_SOA   : 0;
        !           387:                                break;
        !           388:                        case 4:
        !           389:                                type_to_fetch = type_param&PHP_DNS_PTR   ? DNS_TYPE_PTR   : 0;
        !           390:                                break;
        !           391:                        case 5:
        !           392:                                type_to_fetch = type_param&PHP_DNS_HINFO ? DNS_TYPE_HINFO : 0;
        !           393:                                break;
        !           394:                        case 6:
        !           395:                                type_to_fetch = type_param&PHP_DNS_MX    ? DNS_TYPE_MX    : 0;
        !           396:                                break;
        !           397:                        case 7:
        !           398:                                type_to_fetch = type_param&PHP_DNS_TXT   ? DNS_TYPE_TEXT   : 0;
        !           399:                                break;
        !           400:                        case 8:
        !           401:                                type_to_fetch = type_param&PHP_DNS_AAAA  ? DNS_TYPE_AAAA  : 0;
        !           402:                                break;
        !           403:                        case 9:
        !           404:                                type_to_fetch = type_param&PHP_DNS_SRV   ? DNS_TYPE_SRV   : 0;
        !           405:                                break;
        !           406:                        case 10:
        !           407:                                type_to_fetch = type_param&PHP_DNS_NAPTR ? DNS_TYPE_NAPTR : 0;
        !           408:                                break;
        !           409:                        case 11:
        !           410:                                type_to_fetch = type_param&PHP_DNS_A6    ? DNS_TYPE_A6 : 0;
        !           411:                                break;
        !           412:                        case PHP_DNS_NUM_TYPES:
        !           413:                                store_results = 0;
        !           414:                                continue;
        !           415:                        default:
        !           416:                        case (PHP_DNS_NUM_TYPES + 1):
        !           417:                                type_to_fetch = DNS_TYPE_ANY;
        !           418:                                break;
        !           419:                }
        !           420: 
        !           421:                if (type_to_fetch) {
        !           422:                        status = DnsQuery_A(hostname, type_to_fetch, DNS_QUERY_STANDARD, NULL, &pResult, NULL);
        !           423: 
        !           424:                        if (status) {
        !           425:                                if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR) {
        !           426:                                        continue;
        !           427:                                } else {
        !           428:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Dns Query failed");
        !           429:                                        zval_dtor(return_value);
        !           430:                                        RETURN_FALSE;
        !           431:                                }
        !           432:                        }
        !           433: 
        !           434:                        for (pRec = pResult; pRec; pRec = pRec->pNext) {
        !           435:                                DNS_SRV_DATA *srv = &pRec->Data.Srv;
        !           436:                                zval *retval = NULL;
        !           437: 
        !           438:                                if (pRec->Flags.S.Section == DnsSectionAnswer) {
        !           439:                                        php_parserr(pRec, type_to_fetch, store_results, &retval);
        !           440:                                        if (retval != NULL && store_results) {
        !           441:                                                add_next_index_zval(return_value, retval);
        !           442:                                        }
        !           443:                                }
        !           444: 
        !           445:                                if (authns && pRec->Flags.S.Section == DnsSectionAuthority) {
        !           446: 
        !           447:                                        php_parserr(pRec, type_to_fetch, store_results, &retval);
        !           448:                                        if (retval != NULL) {
        !           449:                                                add_next_index_zval(authns, retval);
        !           450:                                        }
        !           451:                                }
        !           452: 
        !           453: /* Stupid typo in PSDK 6.1, WinDNS.h(1258)... */
        !           454: #ifndef DnsSectionAdditional
        !           455: # ifdef DnsSectionAddtional
        !           456: #  define DnsSectionAdditional DnsSectionAddtional
        !           457: # else
        !           458: # define DnsSectionAdditional 3
        !           459: # endif
        !           460: #endif
        !           461:                                if (addtl && pRec->Flags.S.Section == DnsSectionAdditional) {
        !           462:                                        php_parserr(pRec, type_to_fetch, store_results, &retval);
        !           463:                                        if (retval != NULL) {
        !           464:                                                add_next_index_zval(addtl, retval);
        !           465:                                        }
        !           466:                                }
        !           467:                        }
        !           468:                        /* Free memory allocated for DNS records. */
        !           469:                        DnsRecordListFree(pResult, DnsFreeRecordListDeep);
        !           470:                }
        !           471:        }
        !           472: }
        !           473: /* }}} */

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