ares already does htons()
[m6w6/ext-ares] / php_ares.c
index e3f0603e25b28b4a84b440e20e917366974cff2d..2ac6c35a3a979b6fa1af5d831ba84af2f2dc2aa0 100644 (file)
@@ -68,10 +68,23 @@ static int le_ares_query;
 static const char *php_ares_C_names[] = {
        "INVALID",
        "IN",
+       "C2"
        "CHAOS",
-       "HS",
-       "NONE",
-       "ANY",
+       "HS",           /* 4 */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
+       "","","","","","","","","",                                                                             /*  9x */
+       "NONE",         /* 254 */
+       "ANY",          /* 255 */
 };
 
 static const char *php_ares_T_names[] = {
@@ -128,8 +141,6 @@ static const char *php_ares_T_names[] = {
        "","","","","","","","","","","","","","","","","","","","",    /* 20x */
        "","","","","","","","","","","","","","","","","","","","",    /* 20x */
        "","","","","","","","","","","","","","","","","","","","",    /* 20x */
-       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
-       "","","","","","","","","","","","","","","","","","","","",    /* 20x */
        "","","","","","",                                                                                              /*  6x */
        "TKEY", /* 249 */
        "TSIG",
@@ -490,9 +501,26 @@ local void php_ares_query_free(php_ares_query **query) /* {{{ */
 }
 /* }}} */
 
+local zend_bool is_numeric(zval **p, long *lval) { /* {{{ */
+       zval *tmp = *p;
+       switch (Z_TYPE_PP(p)) {
+       case IS_STRING:
+               convert_to_long_ex(&tmp);
+               /* no break */
+       case IS_LONG:
+               *lval = Z_LVAL_P(tmp);
+               if (tmp != *p) {
+                       zval_ptr_dtor(&tmp);
+               }
+               return !!*lval;
+       }
+       return 0;
+} /* }}} */
+
 local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTable *ht) /* {{{ */
 {
        int i;
+       long lval;
        zval **opt, **entry;
        
        if (!options) {
@@ -501,29 +529,35 @@ local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTab
        memset(options, 0, sizeof(php_ares_options));
        
        if (ht && zend_hash_num_elements(ht)) {
-               if ((SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
+               if ((SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &opt)) && is_numeric(opt, &lval)) {
                        options->flags |= ARES_OPT_FLAGS;
-                       options->strct.flags = Z_LVAL_PP(opt);
+                       options->strct.flags = lval;
                }
-               if ((SUCCESS == zend_hash_find(ht, "timeout", sizeof("timeout"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
+#ifdef ARES_OPT_TIMEOUTMS
+               if ((SUCCESS == zend_hash_find(ht, "timeoutms", sizeof("timeoutms"), (void *) &opt)) && is_numeric(opt, &lval)) {
+                       options->flags |= ARES_OPT_TIMEOUTMS;
+                       options->strct.timeout = lval;
+               } else
+#endif
+               if ((SUCCESS == zend_hash_find(ht, "timeout", sizeof("timeout"), (void *) &opt)) && is_numeric(opt, &lval)) {
                        options->flags |= ARES_OPT_TIMEOUT;
-                       options->strct.timeout = Z_LVAL_PP(opt);
+                       options->strct.timeout = lval;
                }
-               if ((SUCCESS == zend_hash_find(ht, "tries", sizeof("tries"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
+               if ((SUCCESS == zend_hash_find(ht, "tries", sizeof("tries"), (void *) &opt)) && is_numeric(opt, &lval)) {
                        options->flags |= ARES_OPT_TRIES;
-                       options->strct.tries = Z_LVAL_PP(opt);
+                       options->strct.tries = lval;
                }
-               if ((SUCCESS == zend_hash_find(ht, "ndots", sizeof("ndots"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
+               if ((SUCCESS == zend_hash_find(ht, "ndots", sizeof("ndots"), (void *) &opt)) && is_numeric(opt, &lval)) {
                        options->flags |= ARES_OPT_NDOTS;
-                       options->strct.ndots = Z_LVAL_PP(opt);
+                       options->strct.ndots = lval;
                }
-               if ((SUCCESS == zend_hash_find(ht, "udp_port", sizeof("udp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
+               if ((SUCCESS == zend_hash_find(ht, "udp_port", sizeof("udp_port"), (void *) &opt)) && is_numeric(opt, &lval)) {
                        options->flags |= ARES_OPT_UDP_PORT;
-                       options->strct.udp_port = htons((unsigned short) Z_LVAL_PP(opt));
+                       options->strct.udp_port = (unsigned short) lval;
                }
-               if ((SUCCESS == zend_hash_find(ht, "tcp_port", sizeof("tcp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
+               if ((SUCCESS == zend_hash_find(ht, "tcp_port", sizeof("tcp_port"), (void *) &opt)) && is_numeric(opt, &lval)) {
                        options->flags |= ARES_OPT_TCP_PORT;
-                       options->strct.tcp_port = htons((unsigned short) Z_LVAL_PP(opt));
+                       options->strct.tcp_port = (unsigned short) lval;
                }
                if ((SUCCESS == zend_hash_find(ht, "servers", sizeof("servers"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_ARRAY) && (i = zend_hash_num_elements(Z_ARRVAL_PP(opt)))) {
                        options->strct.servers = ecalloc(i, sizeof(struct in_addr));
@@ -555,6 +589,17 @@ local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTab
                        options->flags |= ARES_OPT_LOOKUPS;
                        options->strct.lookups = estrdup(Z_STRVAL_PP(opt));
                }
+#ifdef ARES_OPT_ROTATE
+               if ((SUCCESS == zend_hash_find(ht, "rotate", sizeof("rotate"), (void *) &opt)) && i_zend_is_true(*opt)) {
+                       options->flags |= ARES_OPT_ROTATE;
+               }
+#endif
+#ifdef ARES_OPT_EDNSPSZ
+               if ((SUCCESS == zend_hash_find(ht, "ednspsz", sizeof("ednspsz"), (void *) &opt)) && is_numeric(opt, &lval)) {
+                       options->flags |= ARES_OPT_EDNSPSZ;
+                       options->strct.ednspsz = lval;
+               }
+#endif
        }
        
        return options;
@@ -1048,7 +1093,7 @@ static PHP_FUNCTION(ares_init)
        php_ares *ares = NULL;
        int err;
        
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &opt_array)) {
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opt_array)) {
                RETURN_FALSE;
        }
        
@@ -1068,6 +1113,65 @@ static PHP_FUNCTION(ares_init)
 }
 /* }}} */
 
+#ifdef HAVE_ARES_SET_LOCAL_DEV
+/* {{{ proto void ares_set_local_dev(resource ares, string dev)
+        Set the local interface name to bind to. */
+static PHP_FUNCTION(ares_set_local_dev)
+{
+       zval *rsrc;
+       char *dev_str = NULL;
+       int dev_len = 0;
+       php_ares *ares;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!", &rsrc, &dev_str, &dev_len)) {
+               RETURN_FALSE;
+       }
+       ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
+
+       ares_set_local_dev(ares->channel, dev_str);
+}
+#endif
+
+#ifdef HAVE_ARES_SET_LOCAL_IP4
+/* {{{ proto void ares_set_local_ip4(resource ares, int addr)
+        Set the local IPv4 address to bind to. */
+static PHP_FUNCTION(ares_set_local_ip4)
+{
+       zval *rsrc;
+       long ip4_num;
+       php_ares *ares;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &rsrc, &ip4_num)) {
+               RETURN_FALSE;
+       }
+       ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
+
+       ares_set_local_ip4(ares->channel, (unsigned int) ip4_num);
+}
+#endif
+
+#ifdef HAVE_ARES_SET_LOCAL_IP6
+/* {{{ proto void ares_set_local_ip6(resource ares, string addr128bit)
+        Set the local IPv6 address to bind to. */
+static PHP_FUNCTION(ares_set_local_ip6)
+{
+       zval *rsrc;
+       char *ip6_str;
+       int ip6_len;
+       php_ares *ares;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &rsrc, &ip6_str, &ip6_len)) {
+               RETURN_FALSE;
+       }
+       if (16 != ip6_len) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Binary IPv6 address string must be exactly 16 bytes long");
+       }
+       ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
+
+       ares_set_local_ip6(ares->channel, (unsigned char *) ip6_str);
+}
+#endif
+
 /* {{{ proto void ares_destroy(resource ares)
        Destroy the ares handle */
 static PHP_FUNCTION(ares_destroy)
@@ -1725,6 +1829,9 @@ static PHP_MINIT_FUNCTION(ares)
        REGISTER_LONG_CONSTANT("ARES_FLAG_NOSEARCH", ARES_FLAG_NOSEARCH, CONST_PERSISTENT|CONST_CS);
        REGISTER_LONG_CONSTANT("ARES_FLAG_NOALIASES", ARES_FLAG_NOALIASES, CONST_PERSISTENT|CONST_CS);
        REGISTER_LONG_CONSTANT("ARES_FLAG_NOCHECKRESP", ARES_FLAG_NOCHECKRESP, CONST_PERSISTENT|CONST_CS);
+#ifdef ARES_FLAG_EDNS
+       REGISTER_LONG_CONSTANT("ARES_FLAG_EDNS", ARES_FLAG_EDNS, CONST_PERSISTENT|CONST_CS);
+#endif
        
        /*
         * Address Family Constants
@@ -1990,10 +2097,12 @@ static PHP_MINIT_FUNCTION(ares)
 #ifdef T_OPT
        /* (41)  EDNS0 option (meta-RR)  */
         REGISTER_LONG_CONSTANT("ARES_T_OPT", T_OPT, CONST_CS|CONST_PERSISTENT);
+#endif
 #ifdef T_TSIG
        /* (250)  Transaction signature.  */
        REGISTER_LONG_CONSTANT("ARES_T_TSIG", T_TSIG, CONST_CS|CONST_PERSISTENT);
-#endif T_IXFR
+#endif
+#ifdef T_IXFR
        /* (251)  Incremental zone transfer.  */
        REGISTER_LONG_CONSTANT("ARES_T_IXFR", T_IXFR, CONST_CS|CONST_PERSISTENT);
 #endif