LTP GCOV extension - code coverage report
Current view: directory - ext/standard - dns.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 452
Code covered: 3.5 % Executed lines: 16
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 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: The typical suspects                                        |
      16                 :    |          Pollita <pollita@php.net>                                   |
      17                 :    |          Marcus Boerger <helly@php.net>                              |
      18                 :    +----------------------------------------------------------------------+
      19                 :  */
      20                 : 
      21                 : /* $Id: dns.c,v 1.70.2.7.2.2 2007/02/24 02:17:27 helly Exp $ */
      22                 : 
      23                 : /* {{{ includes */
      24                 : #include "php.h"
      25                 : 
      26                 : #if HAVE_SYS_SOCKET_H
      27                 : #include <sys/socket.h>
      28                 : #endif
      29                 : 
      30                 : #ifdef PHP_WIN32
      31                 : #if HAVE_LIBBIND
      32                 : #ifndef WINNT
      33                 : #define WINNT 1
      34                 : #endif
      35                 : /* located in www.php.net/extra/bindlib.zip */
      36                 : #if HAVE_ARPA_INET_H 
      37                 : #include "arpa/inet.h"
      38                 : #endif
      39                 : #include "netdb.h"
      40                 : #if HAVE_ARPA_NAMESERV_H
      41                 : #include "arpa/nameser.h"
      42                 : #endif
      43                 : #if HAVE_RESOLV_H
      44                 : #include "resolv.h"
      45                 : #endif
      46                 : #endif /* HAVE_LIBBIND */
      47                 : #include <winsock2.h>
      48                 : #else   /* This holds good for NetWare too, both for Winsock and Berkeley sockets */
      49                 : #include <netinet/in.h>
      50                 : #if HAVE_ARPA_INET_H
      51                 : #include <arpa/inet.h>
      52                 : #endif
      53                 : #include <netdb.h>
      54                 : #ifdef _OSD_POSIX
      55                 : #undef STATUS
      56                 : #undef T_UNSPEC
      57                 : #endif
      58                 : #if HAVE_ARPA_NAMESER_H
      59                 : #include <arpa/nameser.h>
      60                 : #endif
      61                 : #if HAVE_RESOLV_H
      62                 : #include <resolv.h>
      63                 : #endif
      64                 : #endif
      65                 : 
      66                 : /* Borrowed from SYS/SOCKET.H */
      67                 : #if defined(NETWARE) && defined(USE_WINSOCK)
      68                 : #define AF_INET 2   /* internetwork: UDP, TCP, etc. */
      69                 : #endif
      70                 : 
      71                 : #include "dns.h"
      72                 : 
      73                 : /* type compat */
      74                 : #ifndef DNS_T_A
      75                 : #define DNS_T_A         1
      76                 : #endif
      77                 : #ifndef DNS_T_NS
      78                 : #define DNS_T_NS        2
      79                 : #endif
      80                 : #ifndef DNS_T_CNAME
      81                 : #define DNS_T_CNAME     5
      82                 : #endif
      83                 : #ifndef DNS_T_SOA
      84                 : #define DNS_T_SOA       6
      85                 : #endif
      86                 : #ifndef DNS_T_PTR
      87                 : #define DNS_T_PTR       12
      88                 : #endif
      89                 : #ifndef DNS_T_HINFO
      90                 : #define DNS_T_HINFO     13
      91                 : #endif
      92                 : #ifndef DNS_T_MINFO
      93                 : #define DNS_T_MINFO     14
      94                 : #endif
      95                 : #ifndef DNS_T_MX
      96                 : #define DNS_T_MX        15
      97                 : #endif
      98                 : #ifndef DNS_T_TXT
      99                 : #define DNS_T_TXT       16
     100                 : #endif
     101                 : #ifndef DNS_T_AAAA
     102                 : #define DNS_T_AAAA      28
     103                 : #endif
     104                 : #ifndef DNS_T_SRV
     105                 : #define DNS_T_SRV       33
     106                 : #endif
     107                 : #ifndef DNS_T_NAPTR
     108                 : #define DNS_T_NAPTR     35
     109                 : #endif
     110                 : #ifndef DNS_T_A6
     111                 : #define DNS_T_A6        38
     112                 : #endif
     113                 : 
     114                 : #ifndef DNS_T_ANY
     115                 : #define DNS_T_ANY       255
     116                 : #endif
     117                 : /* }}} */
     118                 : 
     119                 : static char *php_gethostbyaddr(char *ip);
     120                 : static char *php_gethostbyname(char *name);
     121                 : 
     122                 : /* {{{ proto string gethostbyaddr(string ip_address)
     123                 :    Get the Internet host name corresponding to a given IP address */
     124                 : PHP_FUNCTION(gethostbyaddr)
     125               0 : {
     126                 :         zval **arg;
     127                 :         char *addr;     
     128                 :         
     129               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
     130               0 :                 ZEND_WRONG_PARAM_COUNT();
     131                 :         }
     132                 : 
     133               0 :         convert_to_string_ex(arg);
     134                 :         
     135               0 :         addr = php_gethostbyaddr(Z_STRVAL_PP(arg));
     136                 : 
     137               0 :         if (addr == NULL) {
     138                 : #if HAVE_IPV6 && HAVE_INET_PTON
     139               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Address is not a valid IPv4 or IPv6 address");
     140                 : #else
     141                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Address is not in a.b.c.d form");
     142                 : #endif
     143               0 :                 RETVAL_FALSE;
     144                 :         } else {
     145               0 :                 RETVAL_STRING(addr, 0);
     146                 :         }
     147                 : }
     148                 : /* }}} */
     149                 : 
     150                 : /* {{{ php_gethostbyaddr */
     151                 : static char *php_gethostbyaddr(char *ip)
     152               0 : {
     153                 : #if HAVE_IPV6 && HAVE_INET_PTON
     154                 :         struct in6_addr addr6;
     155                 : #endif
     156                 :         struct in_addr addr;
     157                 :         struct hostent *hp;
     158                 : 
     159                 : #if HAVE_IPV6 && HAVE_INET_PTON
     160               0 :         if (inet_pton(AF_INET6, ip, &addr6)) {
     161               0 :                 hp = gethostbyaddr((char *) &addr6, sizeof(addr6), AF_INET6);
     162               0 :         } else if (inet_pton(AF_INET, ip, &addr)) {
     163               0 :                 hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
     164                 :         } else {
     165               0 :                 return NULL;
     166                 :         }
     167                 : #else
     168                 :         addr.s_addr = inet_addr(ip);
     169                 : 
     170                 :         if (addr.s_addr == -1) {
     171                 :                 return NULL;
     172                 :         }
     173                 : 
     174                 :         hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
     175                 : #endif
     176                 : 
     177               0 :         if (!hp || hp->h_name == NULL || hp->h_name[0] == '\0') {
     178               0 :                 return estrdup(ip);
     179                 :         }
     180                 : 
     181               0 :         return estrdup(hp->h_name);
     182                 : }
     183                 : /* }}} */
     184                 : 
     185                 : /* {{{ proto string gethostbyname(string hostname)
     186                 :    Get the IP address corresponding to a given Internet host name */
     187                 : PHP_FUNCTION(gethostbyname)
     188               0 : {
     189                 :         zval **arg;
     190                 :         
     191               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
     192               0 :                 ZEND_WRONG_PARAM_COUNT();
     193                 :         }
     194                 : 
     195               0 :         convert_to_string_ex(arg);
     196                 : 
     197               0 :         RETVAL_STRING(php_gethostbyname(Z_STRVAL_PP(arg)), 0);
     198                 : }
     199                 : /* }}} */
     200                 : 
     201                 : /* {{{ proto array gethostbynamel(string hostname)
     202                 :    Return a list of IP addresses that a given hostname resolves to. */
     203                 : PHP_FUNCTION(gethostbynamel)
     204               0 : {
     205                 :         zval **arg;
     206                 :         struct hostent *hp;
     207                 :         struct in_addr in;
     208                 :         int i;
     209                 : 
     210               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
     211               0 :                 ZEND_WRONG_PARAM_COUNT();
     212                 :         }
     213               0 :         convert_to_string_ex(arg);
     214                 : 
     215               0 :         hp = gethostbyname(Z_STRVAL_PP(arg));
     216               0 :         if (hp == NULL || hp->h_addr_list == NULL) {
     217               0 :                 RETURN_FALSE;
     218                 :         }
     219                 : 
     220               0 :         array_init(return_value);
     221                 : 
     222               0 :         for (i = 0 ; hp->h_addr_list[i] != 0 ; i++) {
     223               0 :                 in = *(struct in_addr *) hp->h_addr_list[i];
     224               0 :                 add_next_index_string(return_value, inet_ntoa(in), 1);
     225                 :         }
     226                 : }
     227                 : /* }}} */
     228                 : 
     229                 : /* {{{ php_gethostbyname */
     230                 : static char *php_gethostbyname(char *name)
     231               0 : {
     232                 :         struct hostent *hp;
     233                 :         struct in_addr in;
     234                 : 
     235               0 :         hp = gethostbyname(name);
     236                 : 
     237               0 :         if (!hp || !*(hp->h_addr_list)) {
     238               0 :                 return estrdup(name);
     239                 :         }
     240                 : 
     241               0 :         memcpy(&in.s_addr, *(hp->h_addr_list), sizeof(in.s_addr));
     242                 : 
     243               0 :         return estrdup(inet_ntoa(in));
     244                 : }
     245                 : /* }}} */
     246                 : 
     247                 : #if HAVE_RES_SEARCH && !(defined(__BEOS__)||defined(PHP_WIN32) || defined(NETWARE))
     248                 : 
     249                 : /* {{{ proto int dns_check_record(string host [, string type])
     250                 :    Check DNS records corresponding to a given Internet host name or IP address */
     251                 : PHP_FUNCTION(dns_check_record)
     252               0 : {
     253                 :         zval **arg1, **arg2;
     254                 :         int type, i;
     255                 : #ifndef MAXPACKET
     256                 : #define MAXPACKET  8192 /* max packet size used internally by BIND */
     257                 : #endif
     258                 :         u_char ans[MAXPACKET];
     259                 :         
     260               0 :         switch (ZEND_NUM_ARGS()) {
     261                 :                 case 1:
     262               0 :                         if (zend_get_parameters_ex(1, &arg1) == FAILURE) {
     263               0 :                                 WRONG_PARAM_COUNT;
     264                 :                         }
     265               0 :                         type = T_MX;
     266               0 :                         convert_to_string_ex(arg1);
     267               0 :                         break;
     268                 : 
     269                 :                 case 2:
     270               0 :                         if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
     271               0 :                                 WRONG_PARAM_COUNT;
     272                 :                         }
     273               0 :                         convert_to_string_ex(arg1);
     274               0 :                         convert_to_string_ex(arg2);
     275                 : 
     276               0 :                         if (!strcasecmp("A", Z_STRVAL_PP(arg2))) type = T_A;
     277               0 :                         else if (!strcasecmp("NS",    Z_STRVAL_PP(arg2))) type = DNS_T_NS;
     278               0 :                         else if (!strcasecmp("MX",    Z_STRVAL_PP(arg2))) type = DNS_T_MX;
     279               0 :                         else if (!strcasecmp("PTR",   Z_STRVAL_PP(arg2))) type = DNS_T_PTR;
     280               0 :                         else if (!strcasecmp("ANY",   Z_STRVAL_PP(arg2))) type = DNS_T_ANY;
     281               0 :                         else if (!strcasecmp("SOA",   Z_STRVAL_PP(arg2))) type = DNS_T_SOA;
     282               0 :                         else if (!strcasecmp("CNAME", Z_STRVAL_PP(arg2))) type = DNS_T_CNAME;
     283               0 :                         else if (!strcasecmp("AAAA",  Z_STRVAL_PP(arg2))) type = DNS_T_AAAA;
     284               0 :                         else if (!strcasecmp("SRV",   Z_STRVAL_PP(arg2))) type = DNS_T_SRV;
     285               0 :                         else if (!strcasecmp("NAPTR", Z_STRVAL_PP(arg2))) type = DNS_T_NAPTR;
     286               0 :                         else if (!strcasecmp("A6", Z_STRVAL_PP(arg2)))    type = DNS_T_A6;
     287                 :                         else {
     288               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%s' not supported", Z_STRVAL_PP(arg2));
     289               0 :                                 RETURN_FALSE;
     290                 :                         }
     291               0 :                         break;
     292                 : 
     293                 :                 default:
     294               0 :                         WRONG_PARAM_COUNT;
     295                 :         }
     296                 : 
     297               0 :         i = res_search(Z_STRVAL_PP(arg1), C_IN, type, ans, sizeof(ans));
     298                 : 
     299               0 :         if (i < 0) {
     300               0 :                 RETURN_FALSE;
     301                 :         }
     302                 : 
     303               0 :         RETURN_TRUE;
     304                 : }
     305                 : /* }}} */
     306                 : 
     307                 : #if HAVE_DNS_FUNCS
     308                 : 
     309                 : #define PHP_DNS_NUM_TYPES       12      /* Number of DNS Types Supported by PHP currently */
     310                 : 
     311                 : #define PHP_DNS_A      0x00000001
     312                 : #define PHP_DNS_NS     0x00000002
     313                 : #define PHP_DNS_CNAME  0x00000010
     314                 : #define PHP_DNS_SOA    0x00000020
     315                 : #define PHP_DNS_PTR    0x00000800
     316                 : #define PHP_DNS_HINFO  0x00001000
     317                 : #define PHP_DNS_MX     0x00004000
     318                 : #define PHP_DNS_TXT    0x00008000
     319                 : #define PHP_DNS_A6     0x01000000
     320                 : #define PHP_DNS_SRV    0x02000000
     321                 : #define PHP_DNS_NAPTR  0x04000000    
     322                 : #define PHP_DNS_AAAA   0x08000000
     323                 : #define PHP_DNS_ANY    0x10000000
     324                 : #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)
     325                 : 
     326             220 : PHP_MINIT_FUNCTION(dns) {
     327             220 :         REGISTER_LONG_CONSTANT("DNS_A",     PHP_DNS_A,     CONST_CS | CONST_PERSISTENT);
     328             220 :         REGISTER_LONG_CONSTANT("DNS_NS",    PHP_DNS_NS,    CONST_CS | CONST_PERSISTENT);
     329             220 :         REGISTER_LONG_CONSTANT("DNS_CNAME", PHP_DNS_CNAME, CONST_CS | CONST_PERSISTENT);
     330             220 :         REGISTER_LONG_CONSTANT("DNS_SOA",   PHP_DNS_SOA,   CONST_CS | CONST_PERSISTENT);
     331             220 :         REGISTER_LONG_CONSTANT("DNS_PTR",   PHP_DNS_PTR,   CONST_CS | CONST_PERSISTENT);
     332             220 :         REGISTER_LONG_CONSTANT("DNS_HINFO", PHP_DNS_HINFO, CONST_CS | CONST_PERSISTENT);
     333             220 :         REGISTER_LONG_CONSTANT("DNS_MX",    PHP_DNS_MX,    CONST_CS | CONST_PERSISTENT);
     334             220 :         REGISTER_LONG_CONSTANT("DNS_TXT",   PHP_DNS_TXT,   CONST_CS | CONST_PERSISTENT);
     335             220 :         REGISTER_LONG_CONSTANT("DNS_SRV",   PHP_DNS_SRV,   CONST_CS | CONST_PERSISTENT);
     336             220 :         REGISTER_LONG_CONSTANT("DNS_NAPTR", PHP_DNS_NAPTR, CONST_CS | CONST_PERSISTENT);
     337             220 :         REGISTER_LONG_CONSTANT("DNS_AAAA",  PHP_DNS_AAAA,  CONST_CS | CONST_PERSISTENT);
     338             220 :         REGISTER_LONG_CONSTANT("DNS_A6",      PHP_DNS_A6,    CONST_CS | CONST_PERSISTENT);
     339             220 :         REGISTER_LONG_CONSTANT("DNS_ANY",   PHP_DNS_ANY,   CONST_CS | CONST_PERSISTENT);
     340             220 :         REGISTER_LONG_CONSTANT("DNS_ALL",   PHP_DNS_ALL,   CONST_CS | CONST_PERSISTENT);
     341             220 :         return SUCCESS;
     342                 : }
     343                 : 
     344                 : #ifndef HFIXEDSZ
     345                 : #define HFIXEDSZ        12      /* fixed data in header <arpa/nameser.h> */
     346                 : #endif /* HFIXEDSZ */
     347                 : 
     348                 : #ifndef QFIXEDSZ
     349                 : #define QFIXEDSZ        4       /* fixed data in query <arpa/nameser.h> */
     350                 : #endif /* QFIXEDSZ */
     351                 : 
     352                 : #undef MAXHOSTNAMELEN
     353                 : #define MAXHOSTNAMELEN  1024
     354                 : 
     355                 : #ifndef MAXRESOURCERECORDS
     356                 : #define MAXRESOURCERECORDS      64
     357                 : #endif /* MAXRESOURCERECORDS */
     358                 : 
     359                 : typedef union {
     360                 :         HEADER qb1;
     361                 :         u_char qb2[65536];
     362                 : } querybuf;
     363                 : 
     364                 : /* just a hack to free resources allocated by glibc in __res_nsend() 
     365                 :  * See also: 
     366                 :  *   res_thread_freeres() in glibc/resolv/res_init.c 
     367                 :  *   __libc_res_nsend()   in resolv/res_send.c 
     368                 :  * */
     369                 : 
     370                 : #ifdef __GLIBC__
     371                 : #define php_dns_free_res(__res__) _php_dns_free_res(__res__)
     372               0 : static void _php_dns_free_res(struct __res_state res) { /* {{{ */
     373                 :         int ns;
     374               0 :         for (ns = 0; ns < MAXNS; ns++) {
     375               0 :                 if (res._u._ext.nsaddrs[ns] != NULL) {
     376               0 :                         free (res._u._ext.nsaddrs[ns]);
     377               0 :                         res._u._ext.nsaddrs[ns] = NULL;
     378                 :                 }
     379                 :         }
     380               0 : } /* }}} */
     381                 : #else
     382                 : #define php_dns_free_res(__res__)
     383                 : #endif
     384                 : 
     385                 : /* {{{ php_parserr */
     386                 : static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, zval **subarray)
     387               0 : {
     388                 :         u_short type, class, dlen;
     389                 :         u_long ttl;
     390                 :         long n, i;
     391                 :         u_short s;
     392                 :         u_char *tp, *p;
     393                 :         char name[MAXHOSTNAMELEN];
     394               0 :         int have_v6_break = 0, in_v6_break = 0;
     395                 : 
     396               0 :         *subarray = NULL;
     397                 : 
     398               0 :         n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2);
     399               0 :         if (n < 0) {
     400               0 :                 return NULL;
     401                 :         }
     402               0 :         cp += n;
     403                 :         
     404               0 :         GETSHORT(type, cp);
     405               0 :         GETSHORT(class, cp);
     406               0 :         GETLONG(ttl, cp);
     407               0 :         GETSHORT(dlen, cp);
     408               0 :         if (type_to_fetch != T_ANY && type != type_to_fetch) {
     409               0 :                 cp += dlen;
     410               0 :                 return cp;
     411                 :         }
     412                 : 
     413               0 :         if (!store) {
     414               0 :                 cp += dlen;
     415               0 :                 return cp;
     416                 :         }
     417                 : 
     418               0 :         ALLOC_INIT_ZVAL(*subarray);
     419               0 :         array_init(*subarray);
     420                 : 
     421               0 :         add_assoc_string(*subarray, "host", name, 1);
     422               0 :         switch (type) {
     423                 :                 case DNS_T_A:
     424               0 :                         add_assoc_string(*subarray, "type", "A", 1);
     425               0 :                         snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
     426               0 :                         add_assoc_string(*subarray, "ip", name, 1);
     427               0 :                         cp += dlen;
     428               0 :                         break;
     429                 :                 case DNS_T_MX:
     430               0 :                         add_assoc_string(*subarray, "type", "MX", 1);
     431               0 :                         GETSHORT(n, cp);
     432               0 :                         add_assoc_long(*subarray, "pri", n);
     433                 :                         /* no break; */
     434                 :                 case DNS_T_CNAME:
     435               0 :                         if (type == DNS_T_CNAME)
     436               0 :                                 add_assoc_string(*subarray, "type", "CNAME", 1);
     437                 :                         /* no break; */
     438                 :                 case DNS_T_NS:
     439               0 :                         if (type == DNS_T_NS)
     440               0 :                                 add_assoc_string(*subarray, "type", "NS", 1);
     441                 :                         /* no break; */
     442                 :                 case DNS_T_PTR:
     443               0 :                         if (type == DNS_T_PTR)
     444               0 :                                 add_assoc_string(*subarray, "type", "PTR", 1);
     445               0 :                         n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
     446               0 :                         if (n < 0) {
     447               0 :                                 return NULL;
     448                 :                         }
     449               0 :                         cp += n;
     450               0 :                         add_assoc_string(*subarray, "target", name, 1);
     451               0 :                         break;
     452                 :                 case DNS_T_HINFO:
     453                 :                         /* See RFC 1010 for values */
     454               0 :                         add_assoc_string(*subarray, "type", "HINFO", 1);
     455               0 :                         n = *cp & 0xFF;
     456               0 :                         cp++;
     457               0 :                         add_assoc_stringl(*subarray, "cpu", cp, n, 1);
     458               0 :                         cp += n;
     459               0 :                         n = *cp & 0xFF;
     460               0 :                         cp++;
     461               0 :                         add_assoc_stringl(*subarray, "os", cp, n, 1);
     462               0 :                         cp += n;
     463               0 :                         break;
     464                 :                 case DNS_T_TXT:
     465               0 :                         add_assoc_string(*subarray, "type", "TXT", 1);
     466               0 :                         n = cp[0];
     467               0 :                         tp = emalloc(n + 1);
     468               0 :                         memcpy(tp, cp + 1, n);
     469               0 :                         tp[n] = '\0';
     470               0 :                         cp += dlen;
     471               0 :                         add_assoc_stringl(*subarray, "txt", tp, n, 0);
     472               0 :                         break;
     473                 :                 case DNS_T_SOA:
     474               0 :                         add_assoc_string(*subarray, "type", "SOA", 1);
     475               0 :                         n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
     476               0 :                         if (n < 0) {
     477               0 :                                 return NULL;
     478                 :                         }
     479               0 :                         cp += n;
     480               0 :                         add_assoc_string(*subarray, "mname", name, 1);
     481               0 :                         n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
     482               0 :                         if (n < 0) {
     483               0 :                                 return NULL;
     484                 :                         }
     485               0 :                         cp += n;
     486               0 :                         add_assoc_string(*subarray, "rname", name, 1);
     487               0 :                         GETLONG(n, cp);
     488               0 :                         add_assoc_long(*subarray, "serial", n);
     489               0 :                         GETLONG(n, cp);
     490               0 :                         add_assoc_long(*subarray, "refresh", n);
     491               0 :                         GETLONG(n, cp);
     492               0 :                         add_assoc_long(*subarray, "retry", n);
     493               0 :                         GETLONG(n, cp);
     494               0 :                         add_assoc_long(*subarray, "expire", n);
     495               0 :                         GETLONG(n, cp);
     496               0 :                         add_assoc_long(*subarray, "minimum-ttl", n);
     497               0 :                         break;
     498                 :                 case DNS_T_AAAA:
     499               0 :                         tp = name;
     500               0 :                         for(i=0; i < 8; i++) {
     501               0 :                                 GETSHORT(s, cp);
     502               0 :                                 if (s != 0) {
     503               0 :                                         if (tp > (u_char *)name) {
     504               0 :                                                 in_v6_break = 0;
     505               0 :                                                 tp[0] = ':';
     506               0 :                                                 tp++;
     507                 :                                         }
     508               0 :                                         tp += sprintf(tp,"%x",s);
     509                 :                                 } else {
     510               0 :                                         if (!have_v6_break) {
     511               0 :                                                 have_v6_break = 1;
     512               0 :                                                 in_v6_break = 1;
     513               0 :                                                 tp[0] = ':';
     514               0 :                                                 tp++;
     515               0 :                                         } else if (!in_v6_break) {
     516               0 :                                                 tp[0] = ':';
     517               0 :                                                 tp++;
     518               0 :                                                 tp[0] = '0';
     519               0 :                                                 tp++;
     520                 :                                         }
     521                 :                                 }
     522                 :                         }
     523               0 :                         if (have_v6_break && in_v6_break) {
     524               0 :                                 tp[0] = ':';
     525               0 :                                 tp++;
     526                 :                         }
     527               0 :                         tp[0] = '\0';
     528               0 :                         add_assoc_string(*subarray, "type", "AAAA", 1);
     529               0 :                         add_assoc_string(*subarray, "ipv6", name, 1);
     530               0 :                         break; 
     531                 :                 case DNS_T_A6:
     532               0 :                         p = cp;
     533               0 :                         add_assoc_string(*subarray, "type", "A6", 1);
     534               0 :                         n = ((int)cp[0]) & 0xFF;
     535               0 :                         cp++;
     536               0 :                         add_assoc_long(*subarray, "masklen", n);
     537               0 :                         tp = name;
     538               0 :                         if (n > 15) {
     539               0 :                                 have_v6_break = 1;
     540               0 :                                 in_v6_break = 1;
     541               0 :                                 tp[0] = ':';
     542               0 :                                 tp++;
     543                 :                         }
     544               0 :                         if (n % 16 > 8) {
     545                 :                                 /* Partial short */
     546               0 :                                 if (cp[0] != 0) {
     547               0 :                                         if (tp > (u_char *)name) {
     548               0 :                                                 in_v6_break = 0;
     549               0 :                                                 tp[0] = ':';
     550               0 :                                                 tp++;
     551                 :                                         }
     552               0 :                                         sprintf(tp, "%x", cp[0] & 0xFF);
     553                 :                                 } else {
     554               0 :                                         if (!have_v6_break) {
     555               0 :                                                 have_v6_break = 1;
     556               0 :                                                 in_v6_break = 1;
     557               0 :                                                 tp[0] = ':';
     558               0 :                                                 tp++;
     559               0 :                                         } else if (!in_v6_break) {
     560               0 :                                                 tp[0] = ':';
     561               0 :                                                 tp++;
     562               0 :                                                 tp[0] = '0';
     563               0 :                                                 tp++;
     564                 :                                         }
     565                 :                                 }
     566               0 :                                 cp++;
     567                 :                         }
     568               0 :                         for(i = (n+8)/16; i < 8; i++) {
     569               0 :                                 GETSHORT(s, cp);
     570               0 :                                 if (s != 0) {
     571               0 :                                         if (tp > (u_char *)name) {
     572               0 :                                                 in_v6_break = 0;
     573               0 :                                                 tp[0] = ':';
     574               0 :                                                 tp++;
     575                 :                                         }
     576               0 :                                         tp += sprintf(tp,"%x",s);
     577                 :                                 } else {
     578               0 :                                         if (!have_v6_break) {
     579               0 :                                                 have_v6_break = 1;
     580               0 :                                                 in_v6_break = 1;
     581               0 :                                                 tp[0] = ':';
     582               0 :                                                 tp++;
     583               0 :                                         } else if (!in_v6_break) {
     584               0 :                                                 tp[0] = ':';
     585               0 :                                                 tp++;
     586               0 :                                                 tp[0] = '0';
     587               0 :                                                 tp++;
     588                 :                                         }
     589                 :                                 }
     590                 :                         }
     591               0 :                         if (have_v6_break && in_v6_break) {
     592               0 :                                 tp[0] = ':';
     593               0 :                                 tp++;
     594                 :                         }
     595               0 :                         tp[0] = '\0';
     596               0 :                         add_assoc_string(*subarray, "ipv6", name, 1);
     597               0 :                         if (cp < p + dlen) {
     598               0 :                                 n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
     599               0 :                                 if (n < 0) {
     600               0 :                                         return NULL;
     601                 :                                 }
     602               0 :                                 cp += n;
     603               0 :                                 add_assoc_string(*subarray, "chain", name, 1);
     604                 :                         }
     605               0 :                         break;
     606                 :                 case DNS_T_SRV:
     607               0 :                         add_assoc_string(*subarray, "type", "SRV", 1);
     608               0 :                         GETSHORT(n, cp);
     609               0 :                         add_assoc_long(*subarray, "pri", n);
     610               0 :                         GETSHORT(n, cp);
     611               0 :                         add_assoc_long(*subarray, "weight", n);
     612               0 :                         GETSHORT(n, cp);
     613               0 :                         add_assoc_long(*subarray, "port", n);
     614               0 :                         n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
     615               0 :                         if (n < 0) {
     616               0 :                                 return NULL;
     617                 :                         }
     618               0 :                         cp += n;
     619               0 :                         add_assoc_string(*subarray, "target", name, 1);
     620               0 :                         break;
     621                 :                 case DNS_T_NAPTR:
     622               0 :                         add_assoc_string(*subarray, "type", "NAPTR", 1);
     623               0 :                         GETSHORT(n, cp);
     624               0 :                         add_assoc_long(*subarray, "order", n);
     625               0 :                         GETSHORT(n, cp);
     626               0 :                         add_assoc_long(*subarray, "pref", n);
     627               0 :                         n = (cp[0] & 0xFF);
     628               0 :                         add_assoc_stringl(*subarray, "flags", ++cp, n, 1);
     629               0 :                         cp += n;
     630               0 :                         n = (cp[0] & 0xFF);
     631               0 :                         add_assoc_stringl(*subarray, "services", ++cp, n, 1);
     632               0 :                         cp += n;
     633               0 :                         n = (cp[0] & 0xFF);
     634               0 :                         add_assoc_stringl(*subarray, "regex", ++cp, n, 1);
     635               0 :                         cp += n;
     636               0 :                         n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
     637               0 :                         if (n < 0) {
     638               0 :                                 return NULL;
     639                 :                         }
     640               0 :                         cp += n;
     641               0 :                         add_assoc_string(*subarray, "replacement", name, 1);
     642               0 :                         break;
     643                 :                 default:
     644               0 :                         cp += dlen;
     645                 :         }
     646                 : 
     647               0 :         add_assoc_string(*subarray, "class", "IN", 1);
     648               0 :         add_assoc_long(*subarray, "ttl", ttl);
     649                 : 
     650               0 :         return cp;
     651                 : }
     652                 : /* }}} */
     653                 : 
     654                 : /* {{{ proto array|false dns_get_record(string hostname [, int type[, array authns, array addtl]])
     655                 :    Get any Resource Record corresponding to a given Internet host name */
     656                 : PHP_FUNCTION(dns_get_record)
     657               0 : {
     658                 :         zval *addtl, *host, *authns, *fetch_type;
     659               0 :         int addtl_recs = 0;
     660               0 :         int type_to_fetch, type_param = PHP_DNS_ANY;
     661                 :         struct __res_state res;
     662                 :         HEADER *hp;
     663                 :         querybuf buf, answer;
     664               0 :         u_char *cp = NULL, *end = NULL;
     665               0 :         int n, qd, an, ns = 0, ar = 0;
     666               0 :         int type, first_query = 1, store_results = 1;
     667                 : 
     668               0 :         switch (ZEND_NUM_ARGS()) {
     669                 :                 case 1:
     670               0 :                         if (zend_get_parameters(ht, 1, &host) == FAILURE) {
     671               0 :                                 WRONG_PARAM_COUNT;
     672                 :                         }
     673               0 :                         break;
     674                 :                 case 2:
     675               0 :                         if (zend_get_parameters(ht, 2, &host, &fetch_type) == FAILURE) {
     676               0 :                                 WRONG_PARAM_COUNT;
     677                 :                         }
     678               0 :                         convert_to_long(fetch_type);
     679               0 :                         type_param = Z_LVAL_P(fetch_type);
     680               0 :                         break;
     681                 :                 case 4:
     682               0 :                         if (zend_get_parameters(ht, 4, &host, &fetch_type, &authns, &addtl) == FAILURE) {
     683               0 :                                 WRONG_PARAM_COUNT;
     684                 :                         }
     685               0 :                         convert_to_long(fetch_type);
     686               0 :                         type_param = Z_LVAL_P(fetch_type);
     687               0 :                         zval_dtor(authns);
     688               0 :                         addtl_recs = 1;         /* We want the additional Records */
     689               0 :                         array_init(authns);
     690               0 :                         zval_dtor(addtl);
     691               0 :                         array_init(addtl);
     692               0 :                         break;
     693                 :                 default:
     694               0 :                         WRONG_PARAM_COUNT;
     695                 :         }
     696                 :         
     697               0 :         convert_to_string(host);
     698                 : 
     699               0 :         if (type_param&~PHP_DNS_ALL && type_param!=PHP_DNS_ANY) {
     700               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%d' not supported", type_param);
     701               0 :                 RETURN_FALSE;
     702                 :         }
     703                 : 
     704                 :         /* Initialize the return array */
     705               0 :         array_init(return_value);
     706                 : 
     707                 :         /* - We emulate an or'ed type mask by querying type by type. (Steps 0 - NUMTYPES-1 )
     708                 :          *   If additional info is wanted we check again with DNS_T_ANY (step NUMTYPES / NUMTYPES+1 )
     709                 :          *   store_results is used to skip storing the results retrieved in step
     710                 :          *   NUMTYPES+1 when results were already fetched.
     711                 :          * - In case of PHP_DNS_ANY we use the directly fetch DNS_T_ANY. (step NUMTYPES+1 )
     712                 :          */
     713               0 :         for(type = (type_param==PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0); type < (addtl_recs ? (PHP_DNS_NUM_TYPES + 2) : PHP_DNS_NUM_TYPES) || first_query; type++)
     714                 :         {
     715               0 :                 first_query = 0;
     716               0 :                 switch (type) {
     717                 :                         case 0: 
     718               0 :                                 type_to_fetch = type_param&PHP_DNS_A     ? DNS_T_A     : 0;
     719               0 :                                 break;
     720                 :                         case 1: 
     721               0 :                                 type_to_fetch = type_param&PHP_DNS_NS    ? DNS_T_NS    : 0;
     722               0 :                                 break;
     723                 :                         case 2: 
     724               0 :                                 type_to_fetch = type_param&PHP_DNS_CNAME ? DNS_T_CNAME : 0;
     725               0 :                                 break;
     726                 :                         case 3: 
     727               0 :                                 type_to_fetch = type_param&PHP_DNS_SOA   ? DNS_T_SOA   : 0;
     728               0 :                                 break;
     729                 :                         case 4: 
     730               0 :                                 type_to_fetch = type_param&PHP_DNS_PTR   ? DNS_T_PTR   : 0;
     731               0 :                                 break;
     732                 :                         case 5: 
     733               0 :                                 type_to_fetch = type_param&PHP_DNS_HINFO ? DNS_T_HINFO : 0;
     734               0 :                                 break;
     735                 :                         case 6: 
     736               0 :                                 type_to_fetch = type_param&PHP_DNS_MX    ? DNS_T_MX    : 0;
     737               0 :                                 break;
     738                 :                         case 7: 
     739               0 :                                 type_to_fetch = type_param&PHP_DNS_TXT   ? DNS_T_TXT   : 0;
     740               0 :                                 break;
     741                 :                         case 8:
     742               0 :                                 type_to_fetch = type_param&PHP_DNS_AAAA      ? DNS_T_AAAA  : 0;
     743               0 :                                 break;
     744                 :                         case 9:
     745               0 :                                 type_to_fetch = type_param&PHP_DNS_SRV   ? DNS_T_SRV   : 0;
     746               0 :                                 break;
     747                 :                         case 10:
     748               0 :                                 type_to_fetch = type_param&PHP_DNS_NAPTR ? DNS_T_NAPTR : 0;
     749               0 :                                 break;
     750                 :                         case 11:
     751               0 :                                 type_to_fetch = type_param&PHP_DNS_A6        ? DNS_T_A6 : 0;
     752               0 :                                 break;
     753                 :                         case PHP_DNS_NUM_TYPES:
     754               0 :                                 store_results = 0;
     755               0 :                                 continue;
     756                 :                         default:
     757                 :                         case (PHP_DNS_NUM_TYPES + 1):
     758               0 :                                 type_to_fetch = DNS_T_ANY;
     759                 :                                 break;
     760                 :                 }
     761               0 :                 if (type_to_fetch) {
     762               0 :                         memset(&res, 0, sizeof(res));
     763               0 :                         res_ninit(&res);
     764               0 :                         res.retrans = 5;
     765               0 :                         res.options &= ~RES_DEFNAMES;
     766                 :                 
     767               0 :                         n = res_nmkquery(&res, QUERY, Z_STRVAL_P(host), C_IN, type_to_fetch, NULL, 0, NULL, buf.qb2, sizeof buf);
     768               0 :                         if (n<0) {
     769               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "res_nmkquery() failed");
     770               0 :                                 zval_dtor(return_value);
     771               0 :                                 res_nclose(&res);
     772               0 :                                 php_dns_free_res(res);
     773               0 :                                 RETURN_FALSE;
     774                 :                         }
     775               0 :                         n = res_nsend(&res, buf.qb2, n, answer.qb2, sizeof answer);
     776               0 :                         if (n<0) {
     777               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "res_nsend() failed");
     778               0 :                                 zval_dtor(return_value);
     779               0 :                                 res_nclose(&res);
     780               0 :                                 php_dns_free_res(res);
     781               0 :                                 RETURN_FALSE;
     782                 :                         }
     783                 :                 
     784               0 :                         cp = answer.qb2 + HFIXEDSZ;
     785               0 :                         end = answer.qb2 + n;
     786               0 :                         hp = (HEADER *)&answer;
     787               0 :                         qd = ntohs(hp->qdcount);
     788               0 :                         an = ntohs(hp->ancount);
     789               0 :                         ns = ntohs(hp->nscount);
     790               0 :                         ar = ntohs(hp->arcount);
     791                 :         
     792                 :                         /* Skip QD entries, they're only used by dn_expand later on */
     793               0 :                         while (qd-- > 0) {
     794               0 :                                 n = dn_skipname(cp, end);
     795               0 :                                 if (n < 0) {
     796               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse DNS data received");
     797               0 :                                         zval_dtor(return_value);
     798               0 :                                         res_nclose(&res);
     799               0 :                                         php_dns_free_res(res);
     800               0 :                                         RETURN_FALSE;
     801                 :                                 }
     802               0 :                                 cp += n + QFIXEDSZ;
     803                 :                         }
     804                 :                 
     805                 :                         /* YAY! Our real answers! */
     806               0 :                         while (an-- && cp && cp < end) {
     807                 :                                 zval *retval;
     808                 : 
     809               0 :                                 cp = php_parserr(cp, &answer, type_to_fetch, store_results, &retval);
     810               0 :                                 if (retval != NULL && store_results) {
     811               0 :                                         add_next_index_zval(return_value, retval);
     812                 :                                 }
     813                 :                         }
     814               0 :                         res_nclose(&res);
     815               0 :                         php_dns_free_res(res);
     816                 :                 }
     817                 :         }
     818                 : 
     819               0 :         if (addtl_recs) {
     820                 :                 /* List of Authoritative Name Servers */
     821               0 :                 while (ns-- > 0 && cp && cp < end) {
     822                 :                         zval *retval;
     823                 : 
     824               0 :                         cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval);
     825               0 :                         if (retval != NULL) {
     826               0 :                                 add_next_index_zval(authns, retval);
     827                 :                         }
     828                 :                 }
     829                 :                 /* Additional records associated with authoritative name servers */
     830               0 :                 while (ar-- > 0 && cp && cp < end) {
     831                 :                         zval *retval;
     832                 : 
     833               0 :                         cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval);
     834               0 :                         if (retval != NULL) {
     835               0 :                                 add_next_index_zval(addtl, retval);
     836                 :                         }
     837                 :                 }
     838                 :         }
     839                 : }
     840                 : /* }}} */
     841                 : #endif /* HAVE_DNS_FUNCS */
     842                 : 
     843                 : #if HAVE_DN_SKIPNAME && HAVE_DN_EXPAND
     844                 : /* {{{ proto bool dns_get_mx(string hostname, array mxhosts [, array weight])
     845                 :    Get MX records corresponding to a given Internet host name */
     846                 : PHP_FUNCTION(dns_get_mx)
     847               0 : {
     848                 :         zval *host, *mx_list, *weight_list;
     849               0 :         int need_weight = 0;
     850                 :         int count, qdc;
     851                 :         u_short type, weight;
     852                 :         u_char ans[MAXPACKET];
     853                 :         char buf[MAXHOSTNAMELEN];
     854                 :         HEADER *hp;
     855                 :         u_char *cp, *end;
     856                 :         int i;
     857                 : 
     858               0 :         switch (ZEND_NUM_ARGS()) {
     859                 :                 case 2:
     860               0 :                         if (zend_get_parameters(ht, 2, &host, &mx_list) == FAILURE) {
     861               0 :                                 WRONG_PARAM_COUNT;
     862                 :                         }
     863               0 :                         break;
     864                 : 
     865                 :                 case 3:
     866               0 :                         if (zend_get_parameters(ht, 3, &host, &mx_list, &weight_list) == FAILURE) {
     867               0 :                                 WRONG_PARAM_COUNT;
     868                 :                         }
     869               0 :                         need_weight = 1;
     870               0 :                         zval_dtor(weight_list); /* start with clean array */
     871               0 :                         array_init(weight_list);
     872               0 :                         break;
     873                 : 
     874                 :                 default:
     875               0 :                         WRONG_PARAM_COUNT;
     876                 :         }
     877                 : 
     878               0 :         convert_to_string(host);
     879               0 :         zval_dtor(mx_list); /* start with clean array */
     880               0 :         array_init(mx_list);
     881                 : 
     882                 :         /* Go! */
     883               0 :         i = res_search(Z_STRVAL_P(host), C_IN, DNS_T_MX, (u_char *)&ans, sizeof(ans));
     884               0 :         if (i < 0) {
     885               0 :                 RETURN_FALSE;
     886                 :         }
     887               0 :         if (i > (int)sizeof(ans)) {
     888               0 :                 i = sizeof(ans);
     889                 :         }
     890               0 :         hp = (HEADER *)&ans;
     891               0 :         cp = (u_char *)&ans + HFIXEDSZ;
     892               0 :         end = (u_char *)&ans +i;
     893               0 :         for (qdc = ntohs((unsigned short)hp->qdcount); qdc--; cp += i + QFIXEDSZ) {
     894               0 :                 if ((i = dn_skipname(cp, end)) < 0 ) {
     895               0 :                         RETURN_FALSE;
     896                 :                 }
     897                 :         }
     898               0 :         count = ntohs((unsigned short)hp->ancount);
     899               0 :         while (--count >= 0 && cp < end) {
     900               0 :                 if ((i = dn_skipname(cp, end)) < 0 ) {
     901               0 :                         RETURN_FALSE;
     902                 :                 }
     903               0 :                 cp += i;
     904               0 :                 GETSHORT(type, cp);
     905               0 :                 cp += INT16SZ + INT32SZ;
     906               0 :                 GETSHORT(i, cp);
     907               0 :                 if (type != DNS_T_MX) {
     908               0 :                         cp += i;
     909               0 :                         continue;
     910                 :                 }
     911               0 :                 GETSHORT(weight, cp);
     912               0 :                 if ((i = dn_expand(ans, end, cp, buf, sizeof(buf)-1)) < 0) {
     913               0 :                         RETURN_FALSE;
     914                 :                 }
     915               0 :                 cp += i;
     916               0 :                 add_next_index_string(mx_list, buf, 1);
     917               0 :                 if (need_weight) {
     918               0 :                         add_next_index_long(weight_list, weight);
     919                 :                 }
     920                 :         }
     921               0 :         RETURN_TRUE;
     922                 : }
     923                 : /* }}} */
     924                 : #endif /* HAVE_DN_SKIPNAME && HAVE_DN_EXPAND */
     925                 : 
     926                 : #endif /* HAVE_RES_SEARCH && !(defined(__BEOS__)||defined(PHP_WIN32) || defined(NETWARE)) */
     927                 : 
     928                 : /*
     929                 :  * Local variables:
     930                 :  * tab-width: 4
     931                 :  * c-basic-offset: 4
     932                 :  * End:
     933                 :  * vim600: sw=4 ts=4 fdm=marker
     934                 :  * vim<600: sw=4 ts=4
     935                 :  */

Generated by: LTP GCOV extension version 1.5