- add pecl/ares
[m6w6/ext-ares] / ares.c
1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2006 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 | Author: |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_ares.h"
29
30 #include <ares.h>
31 #ifdef HAVE_ARES_VERSION
32 # include <ares_version.h>
33 #endif
34 #ifdef HAVE_NETDB_H
35 # include <netdb.h>
36 #endif
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #ifdef HAVE_ARPA_INET_H
41 # include <arpa/inet.h>
42 #endif
43 #ifdef HAVE_ARPA_NAMESER_H
44 # include <arpa/nameser.h>
45 #endif
46
47 #define local inline
48
49 #ifndef ZEND_ENGINE_2
50 # define zend_is_callable(a,b,c) 1
51 #endif
52
53 #define PHP_ARES_LE_NAME "AsyncResolver"
54 #define PHP_ARES_QUERY_LE_NAME "AsyncResolverQuery"
55 static int le_ares;
56 static int le_ares_query;
57
58 #define PHP_ARES_ERROR(err) \
59 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ares_strerror(err))
60 #define RETURN_ARES_ERROR(err) \
61 PHP_ARES_ERROR(err); \
62 RETURN_FALSE
63 #define PHP_ARES_CB_ERROR(param) \
64 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected the " param " argument to be a valid callback")
65 #define RETURN_ARES_CB_ERROR(param) \
66 PHP_ARES_CB_ERROR(param); \
67 RETURN_FALSE
68
69 /* {{{ typedefs */
70 typedef struct _php_ares_options {
71 struct ares_options strct;
72 int flags;
73 } php_ares_options;
74
75 typedef struct _php_ares {
76 ares_channel channel;
77 php_ares_options options;
78 zend_llist queries;
79 TSRMLS_D;
80 unsigned in_callback:1;
81 unsigned reserved:31;
82 } php_ares;
83
84 typedef enum _php_ares_query_type {
85 PHP_ARES_CB_STD,
86 PHP_ARES_CB_HOST,
87 PHP_ARES_CB_NINFO,
88 } php_ares_query_type;
89
90 typedef enum _php_ares_query_packet_type {
91 PHP_ARES_PCKT_SEARCH,
92 PHP_ARES_PCKT_QUERY,
93 PHP_ARES_PCKT_SEND,
94 PHP_ARES_PCKT_HNAME,
95 PHP_ARES_PCKT_HADDR,
96 PHP_ARES_PCKT_NINFO,
97 } php_ares_query_packet_type;
98
99 typedef union _php_ares_query_packet_data {
100 struct {
101 char *name;
102 int name_len;
103 int type;
104 int dnsclass;
105 } search;
106 struct {
107 char *name;
108 int name_len;
109 long type;
110 long dnsclass;
111 } query;
112 struct {
113 char *buf;
114 int len;
115 } send;
116 struct {
117 char *name;
118 int name_len;
119 long family;
120 } hname;
121 struct {
122 char *addr;
123 int addr_len;
124 long family;
125 } haddr;
126 struct {
127 char *addr;
128 int addr_len;
129 long port;
130 long family;
131 long flags;
132 } ninfo;
133 } php_ares_query_packet_data;
134
135 typedef struct _php_ares_query_packet {
136 php_ares_query_packet_type type;
137 php_ares_query_packet_data data;
138 } php_ares_query_packet;
139
140 typedef union _php_ares_query_result {
141 struct {
142 char *buf;
143 int len;
144 } std;
145 struct hostent host;
146 struct {
147 char *service;
148 char *node;
149 } ninfo;
150 } php_ares_query_result;
151
152 typedef struct _php_ares_query {
153 int id;
154 int error;
155 php_ares *ares;
156 zval *callback;
157 php_ares_query_type type;
158 php_ares_query_packet packet;
159 php_ares_query_result result;
160 } php_ares_query;
161 /* }}} */
162
163 local struct hostent *php_ares_hostent_ctor(struct hostent *host) /* {{{ */
164 {
165 if (!host) {
166 host = emalloc(sizeof(struct hostent));
167 }
168 memset(host, 0, sizeof(struct hostent));
169
170 return host;
171 }
172 /* }}} */
173
174 local void php_ares_hostent_copy(struct hostent *from, struct hostent *to) /* {{{ */
175 {
176 int i, c;
177 char **ptr;
178
179 memcpy(to, from, sizeof(struct hostent));
180 to->h_name = estrdup(from->h_name);
181 for (c = 0, ptr = from->h_aliases; *ptr; ++ptr, ++c);
182 to->h_aliases = ecalloc((c+1), sizeof(char *));
183 for (i = 0; i < c; ++i) {
184 to->h_aliases[i] = estrdup(from->h_aliases[i]);
185 }
186 for (c = 0, ptr = from->h_addr_list; *ptr; ++ptr, ++c);
187 to->h_addr_list = ecalloc((c+1), sizeof(char *));
188 for (i = 0; i < c; ++i) {
189 to->h_addr_list[i] = emalloc(from->h_length);
190 memcpy(to->h_addr_list[i], from->h_addr_list[i], from->h_length);
191 }
192 }
193 /* }}} */
194
195 local void php_ares_hostent_to_struct(struct hostent *hostent, HashTable *ht) /* {{{ */
196 {
197 zval array, *tmp;
198 char **ptr;
199
200 INIT_PZVAL(&array);
201 Z_TYPE(array) = IS_ARRAY;
202 Z_ARRVAL(array) = ht;
203
204 if (hostent) {
205 add_assoc_string(&array, "name", hostent->h_name, 1);
206
207 MAKE_STD_ZVAL(tmp);
208 array_init(tmp);
209 if (hostent->h_aliases) {
210 for (ptr = hostent->h_aliases; *ptr; ++ptr) {
211 add_next_index_string(tmp, *ptr, 1);
212 }
213 }
214 add_assoc_zval(&array, "aliases", tmp);
215 add_assoc_long(&array, "addrtype", hostent->h_addrtype);
216
217 MAKE_STD_ZVAL(tmp);
218 array_init(tmp);
219 if (hostent->h_addr_list) {
220 for (ptr = hostent->h_addr_list; *ptr; ++ptr) {
221 char name[64] = {0};
222
223 if (inet_ntop(hostent->h_addrtype, *ptr, name, sizeof(name)-1)) {
224 add_next_index_string(tmp, name, 1);
225 }
226 }
227 }
228 add_assoc_zval(&array, "addrlist", tmp);
229 }
230 }
231 /* }}} */
232
233 local void php_ares_hostent_dtor(struct hostent *host) /* {{{ */
234 {
235 char **ptr;
236
237 STR_FREE(host->h_name);
238 if (host->h_aliases) {
239 for (ptr = host->h_aliases; *ptr; ++ptr) {
240 efree(*ptr);
241 }
242 efree(host->h_aliases);
243 }
244 if (host->h_addr_list) {
245 for (ptr = host->h_addr_list; *ptr; ++ptr) {
246 efree(*ptr);
247 }
248 efree(host->h_addr_list);
249 }
250 memset(host, 0, sizeof(struct hostent));
251 }
252 /* }}} */
253
254 local void php_ares_hostent_free(struct hostent **host) /* {{{ */
255 {
256 php_ares_hostent_dtor(*host);
257 efree(*host);
258 *host = NULL;
259 }
260 /* }}} */
261
262 local php_ares_query *php_ares_query_ctor(php_ares_query *query, php_ares_query_type type, php_ares *ares, zval *callback) /* {{{ */
263 {
264 if (!query) {
265 query = emalloc(sizeof(php_ares_query));
266 }
267 memset(query, 0, sizeof(php_ares_query));
268
269 query->ares = ares;
270 query->type = type;
271 query->error = -1;
272
273 if (callback) {
274 ZVAL_ADDREF(callback);
275 query->callback = callback;
276 }
277
278 return query;
279 }
280 /* }}} */
281
282 local void php_ares_query_rsrc(php_ares_query *query, zval *return_value) /* {{{ */
283 {
284 TSRMLS_FETCH_FROM_CTX(query->ares->tsrm_ls);
285
286 ZEND_REGISTER_RESOURCE(return_value, query, le_ares_query);
287 query->id = Z_LVAL_P(return_value);
288 zend_list_addref(query->id);
289 zend_llist_add_element(&query->ares->queries, &query);
290 }
291 /* }}} */
292
293 local void php_ares_query_pckt(php_ares_query *query, php_ares_query_packet_type type, ...)
294 {
295 va_list argv;
296 char *buf;
297 int len;
298
299 va_start(argv, type);
300
301 switch (query->packet.type = type) {
302 case PHP_ARES_PCKT_SEARCH:
303 buf = va_arg(argv, char *);
304 len = va_arg(argv, int);
305 query->packet.data.search.name = estrndup(buf, len);
306 query->packet.data.search.name_len = len;
307 query->packet.data.search.type = va_arg(argv, long);
308 query->packet.data.search.dnsclass = va_arg(argv, long);
309 break;
310
311 case PHP_ARES_PCKT_QUERY:
312 buf = va_arg(argv, char *);
313 len = va_arg(argv, int);
314 query->packet.data.query.name = estrndup(buf, len);
315 query->packet.data.query.name_len = len;
316 query->packet.data.query.type = va_arg(argv, long);
317 query->packet.data.query.dnsclass = va_arg(argv, long);
318 break;
319
320 case PHP_ARES_PCKT_SEND:
321 buf = va_arg(argv, char *);
322 len = va_arg(argv, int);
323 query->packet.data.send.buf = estrndup(buf, len);
324 query->packet.data.send.len = len;
325 break;
326
327 case PHP_ARES_PCKT_HNAME:
328 buf = va_arg(argv, char *);
329 len = va_arg(argv, int);
330 query->packet.data.hname.name = estrndup(buf, len);
331 query->packet.data.hname.name_len = len;
332 query->packet.data.hname.family = va_arg(argv, long);
333 break;
334
335 case PHP_ARES_PCKT_HADDR:
336 buf = va_arg(argv, char *);
337 len = va_arg(argv, int);
338 query->packet.data.haddr.addr = estrndup(buf, len);
339 query->packet.data.haddr.addr_len = len;
340 query->packet.data.haddr.family = va_arg(argv, long);
341 break;
342
343 case PHP_ARES_PCKT_NINFO:
344 query->packet.data.ninfo.flags = va_arg(argv, long);
345 buf = va_arg(argv, char *);
346 len = va_arg(argv, int);
347 query->packet.data.ninfo.addr = estrndup(buf, len);
348 query->packet.data.ninfo.addr_len = len;
349 query->packet.data.ninfo.family = va_arg(argv, long);
350 query->packet.data.ninfo.port = va_arg(argv, long);
351 break;
352 }
353
354 va_end(argv);
355 }
356
357 local void php_ares_query_dtor(php_ares_query *query) /* {{{ */
358 {
359 struct php_ares_query_packet_buf {char *buf;} *packet;
360
361 packet = (struct php_ares_query_packet_buf *) &query->packet.data;
362 if (packet->buf) {
363 efree(packet->buf);
364 }
365 switch (query->type) {
366 case PHP_ARES_CB_STD:
367 STR_FREE(query->result.std.buf);
368 break;
369 case PHP_ARES_CB_HOST:
370 php_ares_hostent_dtor(&query->result.host);
371 break;
372 case PHP_ARES_CB_NINFO:
373 STR_FREE(query->result.ninfo.service);
374 STR_FREE(query->result.ninfo.node);
375 break;
376 }
377 if (query->callback) {
378 zval_ptr_dtor(&query->callback);
379 }
380 memset(query, 0, sizeof(php_ares_query));
381 }
382 /* }}} */
383
384 local void php_ares_query_free(php_ares_query **query) /* {{{ */
385 {
386 php_ares_query_dtor(*query);
387 efree(*query);
388 *query = NULL;
389 }
390 /* }}} */
391
392 local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTable *ht) /* {{{ */
393 {
394 int i;
395 zval **opt, **entry;
396
397 if (!options) {
398 options = emalloc(sizeof(php_ares_options));
399 }
400 memset(options, 0, sizeof(php_ares_options));
401
402 if (ht && zend_hash_num_elements(ht)) {
403 if ((SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
404 options->flags |= ARES_OPT_FLAGS;
405 options->strct.flags = Z_LVAL_PP(opt);
406 }
407 if ((SUCCESS == zend_hash_find(ht, "timeout", sizeof("timeout"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
408 options->flags |= ARES_OPT_TIMEOUT;
409 options->strct.timeout = Z_LVAL_PP(opt);
410 }
411 if ((SUCCESS == zend_hash_find(ht, "tries", sizeof("tries"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
412 options->flags |= ARES_OPT_TRIES;
413 options->strct.tries = Z_LVAL_PP(opt);
414 }
415 if ((SUCCESS == zend_hash_find(ht, "ndots", sizeof("ndots"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
416 options->flags |= ARES_OPT_NDOTS;
417 options->strct.ndots = Z_LVAL_PP(opt);
418 }
419 if ((SUCCESS == zend_hash_find(ht, "udp_port", sizeof("udp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
420 options->flags |= ARES_OPT_UDP_PORT;
421 options->strct.udp_port = Z_LVAL_PP(opt);
422 }
423 if ((SUCCESS == zend_hash_find(ht, "tcp_port", sizeof("tcp_port"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_LONG)) {
424 options->flags |= ARES_OPT_TCP_PORT;
425 options->strct.tcp_port = Z_LVAL_PP(opt);
426 }
427 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)))) {
428 options->strct.servers = ecalloc(i, sizeof(struct in_addr));
429 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt));
430 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(opt), (void *) &entry);
431 zend_hash_move_forward(Z_ARRVAL_PP(opt))) {
432 if (Z_TYPE_PP(entry) == IS_STRING) {
433 inet_aton(Z_STRVAL_PP(entry), &options->strct.servers[options->strct.nservers++]);
434 }
435 }
436 if (options->strct.nservers) {
437 options->flags |= ARES_OPT_SERVERS;
438 }
439 }
440 if ((SUCCESS == zend_hash_find(ht, "domains", sizeof("domains"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_ARRAY) && (i = zend_hash_num_elements(Z_ARRVAL_PP(opt)))) {
441 options->strct.domains = ecalloc(i, sizeof(char *));
442 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt));
443 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(opt), (void *) &entry);
444 zend_hash_move_forward(Z_ARRVAL_PP(opt))) {
445 if (Z_TYPE_PP(entry) == IS_STRING) {
446 options->strct.domains[options->strct.ndomains++] = estrdup(Z_STRVAL_PP(entry));
447 }
448 }
449 if (options->strct.ndomains) {
450 options->flags |= ARES_OPT_SERVERS;
451 }
452 }
453 if ((SUCCESS == zend_hash_find(ht, "lookups", sizeof("lookups"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_STRING)) {
454 options->flags |= ARES_OPT_LOOKUPS;
455 options->strct.lookups = estrdup(Z_STRVAL_PP(opt));
456 }
457 }
458
459 return options;
460 }
461 /* }}} */
462
463 local void php_ares_options_dtor(php_ares_options *options) /* {{{ */
464 {
465 int i;
466
467 if (options->strct.servers) {
468 efree(options->strct.servers);
469 }
470
471 if (options->strct.domains) {
472 for (i = 0; i < options->strct.ndomains; ++i) {
473 efree(options->strct.domains[i]);
474 }
475 efree(options->strct.domains);
476 }
477
478 STR_FREE(options->strct.lookups);
479
480 memset(options, 0, sizeof(php_ares_options));
481 }
482 /* }}} */
483
484 local void php_ares_options_free(php_ares_options **options) /* {{{ */
485 {
486 php_ares_options_dtor(*options);
487 efree(*options);
488 *options = NULL;
489 }
490 /* }}} */
491
492 /* {{{ callbacks */
493 static void php_ares_callback_func(void *aq, int status, unsigned char *abuf, int alen)
494 {
495 php_ares_query *q = (php_ares_query *) aq;
496 zval *params[3], *retval;
497 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
498
499 q->error = status;
500 if (abuf) {
501 q->result.std.buf = estrndup((char *) abuf, alen);
502 q->result.std.len = alen;
503 }
504
505 if (q->callback) {
506 MAKE_STD_ZVAL(retval);
507 MAKE_STD_ZVAL(params[0]);
508 MAKE_STD_ZVAL(params[1]);
509 MAKE_STD_ZVAL(params[2]);
510 ZVAL_NULL(retval);
511 zend_list_addref(q->id);
512 Z_LVAL_P(params[0]) = q->id;
513 Z_TYPE_P(params[0]) = IS_RESOURCE;
514 ZVAL_LONG(params[1], status);
515 ZVAL_STRINGL(params[2], (char *) abuf, alen, 1);
516
517 q->ares->in_callback = 1;
518 call_user_function(EG(function_table), NULL, q->callback, retval, 3, params TSRMLS_CC);
519 q->ares->in_callback = 0;
520
521 zval_ptr_dtor(&retval);
522 zval_ptr_dtor(&params[0]);
523 zval_ptr_dtor(&params[1]);
524 zval_ptr_dtor(&params[2]);
525 }
526 }
527
528 static void php_ares_host_callback_func(void *aq, int status, struct hostent *hostent)
529 {
530 php_ares_query *q = (php_ares_query *) aq;
531 zval *params[3], *retval;
532 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
533
534 q->error = status;
535 if (hostent) {
536 php_ares_hostent_copy(hostent, &q->result.host);
537 }
538
539 if (q->callback) {
540 MAKE_STD_ZVAL(retval);
541 MAKE_STD_ZVAL(params[0]);
542 MAKE_STD_ZVAL(params[1]);
543 MAKE_STD_ZVAL(params[2]);
544 ZVAL_NULL(retval);
545 zend_list_addref(q->id);
546 Z_LVAL_P(params[0]) = q->id;
547 Z_TYPE_P(params[0]) = IS_RESOURCE;
548 ZVAL_LONG(params[1], status);
549 object_init(params[2]);
550 php_ares_hostent_to_struct(hostent, HASH_OF(params[2]));
551
552 q->ares->in_callback = 1;
553 call_user_function(EG(function_table), NULL, q->callback, retval, 3, params TSRMLS_CC);
554 q->ares->in_callback = 0;
555
556 zval_ptr_dtor(&retval);
557 zval_ptr_dtor(&params[0]);
558 zval_ptr_dtor(&params[1]);
559 zval_ptr_dtor(&params[2]);
560 }
561 }
562
563 #ifdef HAVE_ARES_GETNAMEINFO
564 static void php_ares_nameinfo_callback_func(void *aq, int status, char *node, char *service)
565 {
566 php_ares_query *q = (php_ares_query *) aq;
567 zval *params[4], *retval;
568 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
569
570 q->error = status;
571 if (node) {
572 q->result.ninfo.node = estrdup(node);
573 }
574 if (service) {
575 q->result.ninfo.service = estrdup(service);
576 }
577
578 if (q->callback) {
579 MAKE_STD_ZVAL(retval);
580 MAKE_STD_ZVAL(params[0]);
581 MAKE_STD_ZVAL(params[1]);
582 MAKE_STD_ZVAL(params[2]);
583 MAKE_STD_ZVAL(params[3]);
584 ZVAL_NULL(retval);
585 zend_list_addref(q->id);
586 Z_LVAL_P(params[0]) = q->id;
587 Z_TYPE_P(params[0]) = IS_RESOURCE;
588 ZVAL_LONG(params[1], status);
589 if (node) {
590 ZVAL_STRING(params[2], node, 1);
591 } else {
592 ZVAL_NULL(params[2]);
593 }
594 if (service) {
595 ZVAL_STRING(params[3], service, 1);
596 } else {
597 ZVAL_NULL(params[3]);
598 }
599
600 q->ares->in_callback = 1;
601 call_user_function(EG(function_table), NULL, q->callback, retval, 4, params TSRMLS_CC);
602 q->ares->in_callback = 0;
603
604 zval_ptr_dtor(&retval);
605 zval_ptr_dtor(&params[0]);
606 zval_ptr_dtor(&params[1]);
607 zval_ptr_dtor(&params[2]);
608 zval_ptr_dtor(&params[3]);
609 }
610 }
611 #endif
612 /* }}} */
613
614 local struct timeval *php_ares_timeout(php_ares *ares, long max_timeout, struct timeval *tv_buf) /* {{{ */
615 {
616 struct timeval maxtv;
617
618 if (max_timeout > -1) {
619 maxtv.tv_sec = max_timeout / 1000;
620 maxtv.tv_usec = max_timeout % (max_timeout * 1000);
621 }
622
623 return ares_timeout(ares->channel, max_timeout > -1 ? &maxtv : NULL, tv_buf);
624 }
625 /* }}} */
626
627 local int php_ares_process(php_ares *ares, long max_timeout) /* {{{ */
628 {
629 int nfds;
630 fd_set R, W;
631 struct timeval tv;
632
633 FD_ZERO(&R);
634 FD_ZERO(&W);
635
636 if ((nfds = ares_fds(ares->channel, &R, &W))) {
637 if (0 < select(nfds, &R, &W, NULL, php_ares_timeout(ares, max_timeout, &tv))) {
638 ares_process(ares->channel, &R, &W);
639 }
640 }
641
642 return nfds;
643 }
644 /* }}} */
645
646 local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w) /* {{{ */
647 {
648 int i, nfds = 0;
649
650 for (i = 0; i < FD_SETSIZE; ++i) {
651 if (FD_ISSET(i, R)) {
652 add_next_index_long(r, i);
653 if (i > nfds) {
654 nfds = i;
655 }
656 }
657 }
658
659 for (i = 0; i < FD_SETSIZE; ++i) {
660 if (FD_ISSET(i, W)) {
661 add_next_index_long(w, i);
662 if (i > nfds) {
663 nfds = i;
664 }
665 }
666 }
667
668 return nfds ? nfds + 1 : 0;
669 }
670 /* }}} */
671
672 local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W) /* {{{ */
673 {
674 zval **fd;
675 int nfds = 0;
676
677 if (r && zend_hash_num_elements(Z_ARRVAL_P(r))) {
678 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(r));
679 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(r), (void *) &fd);
680 zend_hash_move_forward(Z_ARRVAL_P(r))) {
681 if (Z_TYPE_PP(fd) == IS_LONG) {
682 FD_SET(Z_LVAL_PP(fd), R);
683 if (Z_LVAL_PP(fd) > nfds) {
684 nfds = Z_LVAL_PP(fd);
685 }
686 }
687 }
688 }
689
690 if (w && zend_hash_num_elements(Z_ARRVAL_P(w))) {
691 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(w));
692 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(w), (void *) &fd);
693 zend_hash_move_forward(Z_ARRVAL_P(w))) {
694 if (Z_TYPE_PP(fd) == IS_LONG) {
695 FD_SET(Z_LVAL_PP(fd), W);
696 if (Z_LVAL_PP(fd) > nfds) {
697 nfds = Z_LVAL_PP(fd);
698 }
699 }
700 }
701 }
702
703 return nfds ? nfds + 1 : 0;
704 }
705 /* }}} */
706
707 static void php_ares_query_llist_dtor(void *entry)
708 {
709 php_ares_query *q = *(php_ares_query **) entry;
710 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
711 zend_list_delete(q->id);
712 }
713
714 #ifdef HAVE_ARES_VERSION
715 /* {{{ proto string ares_version()
716 Get libares version */
717 static PHP_FUNCTION(ares_version)
718 {
719 if (ZEND_NUM_ARGS()) {
720 WRONG_PARAM_COUNT;
721 }
722
723 RETURN_STRING(estrdup(ares_version(NULL)), 0);
724 }
725 /* }}} */
726 #endif
727
728 /* {{{ proto resource ares_init([array options])
729 Create an ares resource */
730 static PHP_FUNCTION(ares_init)
731 {
732 zval *opt_array = NULL;
733 php_ares *ares = NULL;
734 int err;
735
736 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &opt_array)) {
737 RETURN_FALSE;
738 }
739
740 ares = emalloc(sizeof(php_ares));
741 TSRMLS_SET_CTX(ares->tsrm_ls);
742 zend_llist_init(&ares->queries, sizeof(php_ares_query *), (llist_dtor_func_t) php_ares_query_llist_dtor, 0);
743 php_ares_options_ctor(&ares->options, opt_array ? Z_ARRVAL_P(opt_array) : NULL);
744
745 if (ARES_SUCCESS != (err = ares_init_options(&ares->channel, &ares->options.strct, ares->options.flags))) {
746 php_ares_options_dtor(&ares->options);
747 zend_llist_destroy(&ares->queries);
748 efree(ares);
749 RETURN_ARES_ERROR(err);
750 }
751
752 ZEND_REGISTER_RESOURCE(return_value, ares, le_ares);
753 }
754 /* }}} */
755
756 /* {{{ proto void ares_destroy(resource ares)
757 Destroy the ares handle */
758 static PHP_FUNCTION(ares_destroy)
759 {
760 zval *rsrc;
761 php_ares *ares;
762
763 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
764 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
765 if (ares->in_callback) {
766 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy ares handle while in callback");
767 } else {
768 zend_list_delete(Z_LVAL_P(rsrc));
769 }
770 }
771 }
772 /* }}} */
773
774 /* {{{ proto string ares_strerror(int status)
775 Get description of status code */
776 static PHP_FUNCTION(ares_strerror)
777 {
778 long err;
779
780 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &err)) {
781 RETURN_FALSE;
782 }
783
784 RETURN_STRING(estrdup(ares_strerror(err)), 0);
785 }
786 /* }}} */
787
788 /* {{{ proto string ares_mkquery(string name, int dnsclass, int type, int id, int rd)
789 Compose a custom query */
790 static PHP_FUNCTION(ares_mkquery)
791 {
792 char *name_str, *query_str;
793 int name_len, query_len, err;
794 long dnsclass, type, id, rd;
795
796 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &name_str, &name_len, &dnsclass, &type, &id, &rd)) {
797 RETURN_FALSE;
798 }
799
800 if (ARES_SUCCESS != (err = ares_mkquery(name_str, dnsclass, type, id, rd, &query_str, &query_len))) {
801 RETURN_ARES_ERROR(err);
802 }
803 RETVAL_STRINGL(query_str, query_len, 1);
804 ares_free_string(query_str);
805 }
806 /* }}} */
807
808 /* {{{ proto resource ares_search(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
809 Issue a domain search for name */
810 static PHP_FUNCTION(ares_search)
811 {
812 zval *rsrc, *cb = NULL;
813 php_ares *ares;
814 php_ares_query *query;
815 char *name;
816 int name_len;
817 long dnsclass = ns_c_in, type = ns_t_a;
818
819 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
820 RETURN_FALSE;
821 }
822 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
823
824 if (cb && !zend_is_callable(cb, 0, NULL)) {
825 RETURN_ARES_CB_ERROR("second");
826 }
827
828 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
829 php_ares_query_rsrc(query, return_value);
830 php_ares_query_pckt(query, PHP_ARES_PCKT_SEARCH, name, name_len, type, dnsclass);
831 ares_search(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
832 }
833 /* }}} */
834
835 /* {{{ proto resource ares_query(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
836 Issue a single DNS query */
837 static PHP_FUNCTION(ares_query)
838 {
839 zval *rsrc, *cb = NULL;
840 php_ares *ares;
841 php_ares_query *query;
842 char *name;
843 int name_len;
844 long dnsclass = ns_c_in, type = ns_t_a;
845
846 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
847 RETURN_FALSE;
848 }
849 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
850
851 if (cb && !zend_is_callable(cb, 0, NULL)) {
852 RETURN_ARES_CB_ERROR("second");
853 }
854
855 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
856 php_ares_query_rsrc(query, return_value);
857 php_ares_query_pckt(query, PHP_ARES_PCKT_QUERY, name, name_len, type, dnsclass);
858 ares_query(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
859 }
860 /* }}} */
861
862 /* {{{ proto resource ares_send(resource ares, mixed callback, string buf)
863 Send custom query */
864 static PHP_FUNCTION(ares_send)
865 {
866 zval *rsrc, *cb = NULL;
867 php_ares *ares;
868 php_ares_query *query;
869 char *buf;
870 int len;
871
872 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s", &rsrc, &cb, &buf, &len)) {
873 RETURN_FALSE;
874 }
875 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
876
877 if (cb && !zend_is_callable(cb, 0, NULL)) {
878 RETURN_ARES_CB_ERROR("second");
879 }
880
881 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
882 php_ares_query_rsrc(query, return_value);
883 php_ares_query_pckt(query, PHP_ARES_PCKT_SEND, buf, len);
884 ares_send(ares->channel, (const unsigned char *) buf, len, php_ares_callback_func, query);
885 }
886 /* }}} */
887
888 /* {{{ proto resource ares_gethostbyname(resource ares, mixed callback, string name[, int family = AF_INET])
889 Get host by name */
890 static PHP_FUNCTION(ares_gethostbyname)
891 {
892 zval *rsrc, *cb = NULL;
893 php_ares *ares;
894 php_ares_query *query;
895 char *name;
896 int name_len;
897 long family = AF_INET;
898
899 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &name, &name_len, &family)) {
900 RETURN_FALSE;
901 }
902 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
903
904 if (cb && !zend_is_callable(cb, 0, NULL)) {
905 RETURN_ARES_CB_ERROR("second");
906 }
907
908 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
909 php_ares_query_rsrc(query, return_value);
910 php_ares_query_pckt(query, PHP_ARES_PCKT_HNAME, name, name_len, family);
911 ares_gethostbyname(ares->channel, name, family, php_ares_host_callback_func, query);
912 }
913 /* }}} */
914
915 /* {{{ proto resource ares_gethostbyaddr(resuorce ares, mixed callback, string address[, int family = AF_INET])
916 Get host by address */
917 static PHP_FUNCTION(ares_gethostbyaddr)
918 {
919 zval *rsrc, *cb = NULL;
920 php_ares *ares;
921 php_ares_query *query;
922 char *addr;
923 int addr_len;
924 long family = AF_INET;
925 void *sa;
926 int sa_len;
927
928 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &addr, &addr_len, &family)) {
929 RETURN_FALSE;
930 }
931 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
932
933 if (cb && !zend_is_callable(cb, 0, NULL)) {
934 PHP_ARES_CB_ERROR("second");
935 RETURN_FALSE;
936 }
937
938 switch (family) {
939 case AF_INET:
940 sa = emalloc(sa_len = sizeof(struct in_addr));
941 break;
942 case AF_INET6:
943 sa = emalloc(sa_len = sizeof(struct in6_addr));
944 break;
945 default:
946 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither AF_INET nor AF_INET6");
947 RETURN_FALSE;
948 break;
949 }
950
951 if (1 > inet_pton(family, addr, sa)) {
952 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
953 RETVAL_FALSE;
954 } else {
955 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
956 php_ares_query_rsrc(query, return_value);
957 php_ares_query_pckt(query, PHP_ARES_PCKT_HADDR, addr, addr_len, family);
958 ares_gethostbyaddr(ares->channel, sa, sa_len, family, php_ares_host_callback_func, query);
959 }
960 efree(sa);
961 }
962 /* }}} */
963
964 #ifdef HAVE_ARES_GETNAMEINFO
965 /* {{{ proto resource ares_getnameinfo(resource ares, mixed callback, int flags, string addr[, int family[, int port]])
966 Get name info */
967 static PHP_FUNCTION(ares_getnameinfo)
968 {
969 zval *rsrc, *cb = NULL;
970 php_ares *ares;
971 php_ares_query *query;
972 char *addr;
973 int addr_len;
974 long flags, port = 0, family = AF_INET;
975 struct sockaddr *sa;
976 struct sockaddr_in *in;
977 struct sockaddr_in6 *in6;
978 int sa_len;
979
980 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!ls|ll", &rsrc, &cb, &flags, &addr, &addr_len, &family, &port)) {
981 RETURN_FALSE;
982 }
983 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
984
985 if (cb && !zend_is_callable(cb, 0, NULL)) {
986 PHP_ARES_CB_ERROR("second");
987 RETURN_FALSE;
988 }
989
990 RETVAL_TRUE;
991 switch (family) {
992 case AF_INET:
993 in = emalloc(sa_len = sizeof(struct sockaddr_in));
994 in->sin_family = AF_INET;
995 in->sin_port = port;
996 if (1 > inet_pton(in->sin_family, addr, &in->sin_addr)) {
997 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
998 RETVAL_FALSE;
999 }
1000 sa = (struct sockaddr *) in;
1001 break;
1002 case AF_INET6:
1003 in6 = emalloc(sa_len = sizeof(struct sockaddr_in6));
1004 in6->sin6_family = AF_INET6;
1005 in6->sin6_port = port;
1006 if (1 > inet_pton(in6->sin6_family, addr, &in6->sin6_addr)) {
1007 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1008 RETVAL_FALSE;
1009 }
1010 sa = (struct sockaddr *) in6;
1011 break;
1012 default:
1013 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither AF_INET nor AF_INET6");
1014 RETURN_FALSE;
1015 break;
1016 }
1017
1018 if (Z_BVAL_P(return_value)) {
1019 query = php_ares_query_ctor(NULL, PHP_ARES_CB_NINFO, ares, cb);
1020 php_ares_query_rsrc(query, return_value);
1021 php_ares_query_pckt(query, PHP_ARES_PCKT_NINFO, flags, addr, addr_len, family, port);
1022 ares_getnameinfo(ares->channel, sa, sa_len, flags, php_ares_nameinfo_callback_func, query);
1023 }
1024 efree(sa);
1025 }
1026 /* }}} */
1027 #endif
1028
1029 /* {{{ proto mixed ares_result(resource query, int &errno, string &error)
1030 Check a query for its result */
1031 static PHP_FUNCTION(ares_result)
1032 {
1033 zval *rsrc, *zerrno = NULL, *zerror = NULL;
1034 php_ares_query *query;
1035
1036 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &rsrc, &zerrno, &zerror)) {
1037 RETURN_FALSE;
1038 }
1039 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1040
1041 if (zerrno) {
1042 zval_dtor(zerrno);
1043 ZVAL_LONG(zerrno, query->error);
1044 }
1045 if (zerror) {
1046 zval_dtor(zerror);
1047 ZVAL_NULL(zerror);
1048 }
1049
1050 switch (query->error) {
1051 case 0:
1052 switch (query->type) {
1053 case PHP_ARES_CB_STD:
1054 RETVAL_STRINGL(query->result.std.buf, query->result.std.len, 1);
1055 break;
1056 case PHP_ARES_CB_HOST:
1057 object_init(return_value);
1058 php_ares_hostent_to_struct(&query->result.host, HASH_OF(return_value));
1059 break;
1060 case PHP_ARES_CB_NINFO:
1061 object_init(return_value);
1062 add_property_string(return_value, "node", query->result.ninfo.node ? query->result.ninfo.node : "", 1);
1063 add_property_string(return_value, "service", query->result.ninfo.service ? query->result.ninfo.service : "", 1);
1064 break;
1065 }
1066 break;
1067 case -1:
1068 RETVAL_FALSE;
1069 break;
1070 default:
1071 if (zerror) {
1072 ZVAL_STRING(zerror, estrdup(ares_strerror(query->error)), 0);
1073 }
1074 RETVAL_FALSE;
1075 break;
1076 }
1077 }
1078 /* }}} */
1079
1080 /* {{{ proto object ares_packet(resource query)
1081 Check a query for its question packet */
1082 static PHP_FUNCTION(ares_packet)
1083 {
1084 zval *rsrc, *prop;
1085 php_ares_query *query;
1086
1087 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1088 RETURN_FALSE;
1089 }
1090 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1091
1092 object_init(return_value);
1093 add_property_long(return_value, "type", query->packet.type);
1094 add_property_null(return_value, "search");
1095 add_property_null(return_value, "query");
1096 add_property_null(return_value, "send");
1097 add_property_null(return_value, "gethostbyname");
1098 add_property_null(return_value, "gethostbyaddr");
1099 add_property_null(return_value, "getnameinfo");
1100 MAKE_STD_ZVAL(prop);
1101
1102 switch (query->packet.type) {
1103 case PHP_ARES_PCKT_SEARCH:
1104 object_init(prop);
1105 add_property_stringl(prop, "name", query->packet.data.search.name, query->packet.data.search.name_len, 1);
1106 add_property_long(prop, "type", query->packet.data.search.type);
1107 add_property_long(prop, "dnsclass", query->packet.data.search.dnsclass);
1108 add_property_zval(return_value, "search", prop);
1109 break;
1110
1111 case PHP_ARES_PCKT_QUERY:
1112 object_init(prop);
1113 add_property_stringl(prop, "name", query->packet.data.query.name, query->packet.data.query.name_len, 1);
1114 add_property_long(prop, "type", query->packet.data.query.type);
1115 add_property_long(prop, "dnsclass", query->packet.data.query.dnsclass);
1116 add_property_zval(return_value, "query", prop);
1117 break;
1118
1119 case PHP_ARES_PCKT_SEND:
1120 ZVAL_STRINGL(prop, query->packet.data.send.buf, query->packet.data.send.len, 1);
1121 add_property_zval(return_value, "send", prop);
1122 break;
1123
1124 case PHP_ARES_PCKT_HNAME:
1125 object_init(prop);
1126 add_property_stringl(prop, "name", query->packet.data.hname.name, query->packet.data.hname.name_len, 1);
1127 add_property_long(prop, "family", query->packet.data.hname.family);
1128 add_property_zval(return_value, "gethostbyname", prop);
1129 break;
1130
1131 case PHP_ARES_PCKT_HADDR:
1132 object_init(prop);
1133 add_property_stringl(prop, "addr", query->packet.data.haddr.addr, query->packet.data.haddr.addr_len, 1);
1134 add_property_long(prop, "family", query->packet.data.haddr.family);
1135 add_property_zval(return_value, "gethostbyaddr", prop);
1136 break;
1137
1138 case PHP_ARES_PCKT_NINFO:
1139 object_init(prop);
1140 add_property_long(prop, "flags", query->packet.data.ninfo.flags);
1141 add_property_stringl(prop, "addr", query->packet.data.ninfo.addr, query->packet.data.ninfo.addr_len, 1);
1142 add_property_long(prop, "family", query->packet.data.ninfo.family);
1143 add_property_long(prop, "port", query->packet.data.ninfo.port);
1144 add_property_zval(return_value, "getnameinfo", prop);
1145 break;
1146 }
1147
1148 zval_ptr_dtor(&prop);
1149 }
1150 /* }}} */
1151
1152 #ifdef HAVE_ARES_CANCEL
1153 /* {{{ proto void ares_cancel(resource ares)
1154 Cancel pending queries */
1155 static PHP_FUNCTION(ares_cancel)
1156 {
1157 zval *rsrc;
1158 php_ares *ares;
1159
1160 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1161 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1162 ares_cancel(ares->channel);
1163 }
1164 }
1165 /* }}} */
1166 #endif
1167
1168 /* {{{ proto void ares_process_all(resource ares[, int max_timeout_ms])
1169 Process all pending queries */
1170 static PHP_FUNCTION(ares_process_all)
1171 {
1172 zval *rsrc;
1173 php_ares *ares;
1174 long max_timeout = -1;
1175
1176 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1177 RETURN_FALSE;
1178 }
1179 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1180
1181 while (php_ares_process(ares, max_timeout));
1182 }
1183 /* }}} */
1184
1185 /* {{{ proto bool ares_process_once(resource ares[, int max_timout_ms])
1186 Process once and return whether it should be called again */
1187 static PHP_FUNCTION(ares_process_once)
1188 {
1189 zval *rsrc;
1190 php_ares *ares;
1191 long max_timeout = -1;
1192
1193 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1194 RETURN_FALSE;
1195 }
1196 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1197
1198 RETVAL_BOOL(php_ares_process(ares, max_timeout));
1199 }
1200 /* }}} */
1201
1202 /* {{{ proto void ares_process(resource ares, array read, array write)
1203 Process call */
1204 static PHP_FUNCTION(ares_process)
1205 {
1206 zval *rsrc, *read = NULL, *write = NULL;
1207 fd_set R, W;
1208 php_ares *ares;
1209
1210 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a!a!", &rsrc, &read, &write)) {
1211 RETURN_FALSE;
1212 }
1213 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1214
1215 FD_ZERO(&R);
1216 FD_ZERO(&W);
1217
1218 php_ares_extract_fds(read, write, &R, &W);
1219 ares_process(ares->channel, &R, &W);
1220 }
1221 /* }}} */
1222
1223 /* proto bool ares_select(array &read, array &write, int timeout_ms)
1224 Select call */
1225 static PHP_FUNCTION(ares_select)
1226 {
1227 zval *read = NULL, *write = NULL;
1228 fd_set R, W;
1229 int nfds;
1230 long timeout;
1231 struct timeval tv;
1232
1233 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aal", &read, &write, &timeout)) {
1234 RETURN_FALSE;
1235 }
1236
1237 if (timeout) {
1238 tv.tv_sec = timeout / 1000;
1239 tv.tv_usec = timeout % (timeout * 1000);
1240 } else {
1241 tv.tv_sec = 1;
1242 tv.tv_usec = 0;
1243 }
1244
1245 FD_ZERO(&R);
1246 FD_ZERO(&W);
1247
1248 nfds = php_ares_extract_fds(read, write, &R, &W);
1249 if (-1 < select(nfds, &R, &W, NULL, &tv)) {
1250 zend_hash_clean(Z_ARRVAL_P(read));
1251 zend_hash_clean(Z_ARRVAL_P(write));
1252 php_ares_publish_fds(&R, &W, read, write);
1253 RETURN_TRUE;
1254 }
1255 RETURN_FALSE;
1256 }
1257 /* }}} */
1258
1259 /* proto int ares_timeout(resource ares[, int max_timout_ms])
1260 Get suggested select timeout in ms */
1261 static PHP_FUNCTION(ares_timeout)
1262 {
1263 zval *rsrc;
1264 long max_timeout = -1;
1265 struct timeval tv, *tvptr;
1266 php_ares *ares;
1267
1268 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1269 RETURN_FALSE;
1270 }
1271 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1272
1273 if ((tvptr = php_ares_timeout(ares, max_timeout, &tv))) {
1274 RETURN_LONG(tvptr->tv_sec * 1000 + tvptr->tv_usec / 1000);
1275 }
1276 RETURN_LONG(0);
1277 }
1278 /* }}} */
1279
1280 /* {{{ proto int ares_fds(resource ares, array &read, array &write)
1281 Get file descriptors */
1282 static PHP_FUNCTION(ares_fds)
1283 {
1284 zval *rsrc, *read, *write;
1285 fd_set R, W;
1286 php_ares *ares;
1287
1288 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz", &rsrc, &read, &write)) {
1289 RETURN_FALSE;
1290 }
1291 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1292
1293 FD_ZERO(&R);
1294 FD_ZERO(&W);
1295
1296 zval_dtor(read);
1297 zval_dtor(write);
1298 array_init(read);
1299 array_init(write);
1300 ares_fds(ares->channel, &R, &W);
1301 RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write));
1302 }
1303 /* }}} */
1304
1305
1306 /* {{{ proto array ares_parse_a_reply(string reply)
1307 Parse an A reply */
1308 static PHP_FUNCTION(ares_parse_a_reply)
1309 {
1310 char *buf;
1311 int len, err;
1312 struct hostent *hostent;
1313
1314 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &len)) {
1315 RETURN_FALSE;
1316 }
1317
1318 if (ARES_SUCCESS != (err = ares_parse_a_reply((const unsigned char *) buf, len, &hostent))) {
1319 RETURN_ARES_ERROR(err);
1320 }
1321
1322 object_init(return_value);
1323 php_ares_hostent_to_struct(hostent, HASH_OF(return_value));
1324 ares_free_hostent(hostent);
1325 }
1326 /* }}} */
1327
1328 #ifdef HAVE_ARES_PARSE_AAAA_REPLY
1329 /* {{{ proto array ares_parse_aaaa_reply(string reply)
1330 Parse an AAAA reply */
1331 static PHP_FUNCTION(ares_parse_aaaa_reply)
1332 {
1333 char *buf;
1334 int len, err;
1335 struct hostent *hostent;
1336
1337 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &len)) {
1338 RETURN_FALSE;
1339 }
1340
1341 if (ARES_SUCCESS != (err = ares_parse_aaaa_reply((const unsigned char *) buf, len, &hostent))) {
1342 RETURN_ARES_ERROR(err);
1343 }
1344
1345 object_init(return_value);
1346 php_ares_hostent_to_struct(hostent, HASH_OF(return_value));
1347 ares_free_hostent(hostent);
1348 }
1349 /* }}} */
1350 #endif
1351
1352 /* {{{ proto array ares_parse_ptr_reply(string reply)
1353 Parse a PTR reply */
1354 static PHP_FUNCTION(ares_parse_ptr_reply)
1355 {
1356 char *buf;
1357 int len, err;
1358 struct hostent *hostent;
1359
1360 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &len)) {
1361 RETURN_FALSE;
1362 }
1363
1364 if (ARES_SUCCESS != (err = ares_parse_ptr_reply((const unsigned char *) buf, len, NULL, 0, 0, &hostent))) {
1365 RETURN_ARES_ERROR(err);
1366 }
1367
1368 object_init(return_value);
1369 php_ares_hostent_to_struct(hostent, HASH_OF(return_value));
1370 ares_free_hostent(hostent);
1371 }
1372 /* }}} */
1373
1374 /* {{{ proto string ares_expand_name(string name)
1375 Expand a DNS encoded name into a human readable dotted string */
1376 static PHP_FUNCTION(ares_expand_name)
1377 {
1378 char *name_str, *exp_str;
1379 int name_len,err;
1380 PHP_ARES_EXPAND_LEN_TYPE exp_len;
1381
1382 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
1383 RETURN_FALSE;
1384 }
1385
1386 if (ARES_SUCCESS != (err = ares_expand_name((const unsigned char *) name_str, (const unsigned char *) name_str, name_len, &exp_str, &exp_len))) {
1387 RETURN_ARES_ERROR(err);
1388 }
1389 RETVAL_STRINGL(exp_str, exp_len, 1);
1390 ares_free_string(exp_str);
1391 }
1392 /* }}} */
1393
1394 #ifdef HAVE_ARES_EXPAND_STRING
1395 /* {{{ proto string ares_expand_string(string buf)
1396 Expand a DNS encoded string into a human readable */
1397 static PHP_FUNCTION(ares_expand_string)
1398 {
1399 char *buf_str, *exp_str;
1400 int buf_len, err;
1401 PHP_ARES_EXPAND_LEN_TYPE exp_len;
1402
1403 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf_str, &buf_len)) {
1404 RETURN_FALSE;
1405 }
1406
1407 if (ARES_SUCCESS != (err = ares_expand_string((const unsigned char *) buf_str, (const unsigned char *) buf_str, buf_len, &exp_str, &exp_len))) {
1408 RETURN_ARES_ERROR(err);
1409 }
1410 RETVAL_STRINGL(exp_str, exp_len, 1);
1411 ares_free_string(exp_str);
1412 }
1413 /* }}} */
1414 #endif
1415
1416 static ZEND_RSRC_DTOR_FUNC(php_ares_le_dtor)
1417 {
1418 php_ares *ares = (php_ares *) rsrc->ptr;
1419
1420 ares_destroy(ares->channel);
1421 zend_llist_destroy(&ares->queries);
1422 php_ares_options_dtor(&ares->options);
1423 efree(ares);
1424 }
1425
1426 static ZEND_RSRC_DTOR_FUNC(php_ares_query_le_dtor)
1427 {
1428 php_ares_query *query = (php_ares_query *) rsrc->ptr;
1429
1430 php_ares_query_dtor(query);
1431 efree(query);
1432 }
1433
1434 /* {{{ PHP_MINIT_FUNCTION */
1435 static PHP_MINIT_FUNCTION(ares)
1436 {
1437 #ifdef HAVE_ARES_VERSION
1438 int ares_version_num;
1439 ares_version(&ares_version_num);
1440
1441 REGISTER_LONG_CONSTANT("ARES_VERSION", ares_version_num, CONST_PERSISTENT|CONST_CS);
1442 #endif
1443
1444 REGISTER_LONG_CONSTANT("ARES_SUCCESS", ARES_SUCCESS, CONST_PERSISTENT|CONST_CS);
1445 REGISTER_LONG_CONSTANT("ARES_ENODATA", ARES_ENODATA, CONST_PERSISTENT|CONST_CS);
1446 REGISTER_LONG_CONSTANT("ARES_EFORMERR", ARES_EFORMERR, CONST_PERSISTENT|CONST_CS);
1447 REGISTER_LONG_CONSTANT("ARES_ESERVFAIL", ARES_ESERVFAIL, CONST_PERSISTENT|CONST_CS);
1448 REGISTER_LONG_CONSTANT("ARES_ENOTFOUND", ARES_ENOTFOUND, CONST_PERSISTENT|CONST_CS);
1449 REGISTER_LONG_CONSTANT("ARES_ENOTIMP", ARES_ENOTIMP, CONST_PERSISTENT|CONST_CS);
1450 REGISTER_LONG_CONSTANT("ARES_EREFUSED", ARES_EREFUSED, CONST_PERSISTENT|CONST_CS);
1451 REGISTER_LONG_CONSTANT("ARES_EBADQUERY", ARES_EBADQUERY, CONST_PERSISTENT|CONST_CS);
1452 REGISTER_LONG_CONSTANT("ARES_EBADNAME", ARES_EBADNAME, CONST_PERSISTENT|CONST_CS);
1453 REGISTER_LONG_CONSTANT("ARES_EBADFAMILY", ARES_EBADFAMILY, CONST_PERSISTENT|CONST_CS);
1454 REGISTER_LONG_CONSTANT("ARES_EBADRESP", ARES_EBADRESP, CONST_PERSISTENT|CONST_CS);
1455 REGISTER_LONG_CONSTANT("ARES_ECONNREFUSED", ARES_ECONNREFUSED, CONST_PERSISTENT|CONST_CS);
1456 REGISTER_LONG_CONSTANT("ARES_ETIMEOUT", ARES_ETIMEOUT, CONST_PERSISTENT|CONST_CS);
1457 REGISTER_LONG_CONSTANT("ARES_EOF", ARES_EOF, CONST_PERSISTENT|CONST_CS);
1458 REGISTER_LONG_CONSTANT("ARES_EFILE", ARES_EFILE, CONST_PERSISTENT|CONST_CS);
1459 REGISTER_LONG_CONSTANT("ARES_ENOMEM", ARES_ENOMEM, CONST_PERSISTENT|CONST_CS);
1460 REGISTER_LONG_CONSTANT("ARES_EDESTRUCTION", ARES_EDESTRUCTION, CONST_PERSISTENT|CONST_CS);
1461 #ifdef ARES_EBADSTR
1462 REGISTER_LONG_CONSTANT("ARES_EBADSTR", ARES_EBADSTR, CONST_PERSISTENT|CONST_CS);
1463 #endif
1464 #ifdef ARES_EBADFLAGS
1465 REGISTER_LONG_CONSTANT("ARES_EBADFLAGS", ARES_EBADFLAGS, CONST_PERSISTENT|CONST_CS);
1466 #endif
1467 #ifdef ARES_ENONAME
1468 REGISTER_LONG_CONSTANT("ARES_ENONAME", ARES_ENONAME, CONST_PERSISTENT|CONST_CS);
1469 #endif
1470 #ifdef ARES_EBADHINTS
1471 REGISTER_LONG_CONSTANT("ARES_EBADHINTS", ARES_EBADHINTS, CONST_PERSISTENT|CONST_CS);
1472 #endif
1473
1474 REGISTER_LONG_CONSTANT("ARES_FLAG_USEVC", ARES_FLAG_USEVC, CONST_PERSISTENT|CONST_CS);
1475 REGISTER_LONG_CONSTANT("ARES_FLAG_PRIMARY", ARES_FLAG_PRIMARY, CONST_PERSISTENT|CONST_CS);
1476 REGISTER_LONG_CONSTANT("ARES_FLAG_IGNTC", ARES_FLAG_IGNTC, CONST_PERSISTENT|CONST_CS);
1477 REGISTER_LONG_CONSTANT("ARES_FLAG_NORECURSE", ARES_FLAG_NORECURSE, CONST_PERSISTENT|CONST_CS);
1478 REGISTER_LONG_CONSTANT("ARES_FLAG_STAYOPEN", ARES_FLAG_STAYOPEN, CONST_PERSISTENT|CONST_CS);
1479 REGISTER_LONG_CONSTANT("ARES_FLAG_NOSEARCH", ARES_FLAG_NOSEARCH, CONST_PERSISTENT|CONST_CS);
1480 REGISTER_LONG_CONSTANT("ARES_FLAG_NOALIASES", ARES_FLAG_NOALIASES, CONST_PERSISTENT|CONST_CS);
1481 REGISTER_LONG_CONSTANT("ARES_FLAG_NOCHECKRESP", ARES_FLAG_NOCHECKRESP, CONST_PERSISTENT|CONST_CS);
1482
1483 REGISTER_LONG_CONSTANT("ARES_OPT_FLAGS", ARES_OPT_FLAGS, CONST_PERSISTENT|CONST_CS);
1484 REGISTER_LONG_CONSTANT("ARES_OPT_TIMEOUT", ARES_OPT_TIMEOUT, CONST_PERSISTENT|CONST_CS);
1485 REGISTER_LONG_CONSTANT("ARES_OPT_TRIES", ARES_OPT_TRIES, CONST_PERSISTENT|CONST_CS);
1486 REGISTER_LONG_CONSTANT("ARES_OPT_NDOTS", ARES_OPT_NDOTS, CONST_PERSISTENT|CONST_CS);
1487 REGISTER_LONG_CONSTANT("ARES_OPT_UDP_PORT", ARES_OPT_UDP_PORT, CONST_PERSISTENT|CONST_CS);
1488 REGISTER_LONG_CONSTANT("ARES_OPT_TCP_PORT", ARES_OPT_TCP_PORT, CONST_PERSISTENT|CONST_CS);
1489 REGISTER_LONG_CONSTANT("ARES_OPT_SERVERS", ARES_OPT_SERVERS, CONST_PERSISTENT|CONST_CS);
1490 REGISTER_LONG_CONSTANT("ARES_OPT_DOMAINS", ARES_OPT_DOMAINS, CONST_PERSISTENT|CONST_CS);
1491 REGISTER_LONG_CONSTANT("ARES_OPT_LOOKUPS", ARES_OPT_LOOKUPS, CONST_PERSISTENT|CONST_CS);
1492
1493 /*
1494 * Name Info constants
1495 */
1496 #ifdef ARES_NI_NOFQDN
1497 REGISTER_LONG_CONSTANT("ARES_NI_NOFQDN", ARES_NI_NOFQDN, CONST_PERSISTENT|CONST_CS);
1498 #endif
1499 #ifdef ARES_NI_NUMERICHOST
1500 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICHOST", ARES_NI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
1501 #endif
1502 #ifdef ARES_NI_NAMEREQD
1503 REGISTER_LONG_CONSTANT("ARES_NI_NAMEREQD", ARES_NI_NAMEREQD, CONST_PERSISTENT|CONST_CS);
1504 #endif
1505 #ifdef ARES_NI_NUMERICSERV
1506 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSERV", ARES_NI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
1507 #endif
1508 #ifdef ARES_NI_DGRAM
1509 REGISTER_LONG_CONSTANT("ARES_NI_DGRAM", ARES_NI_DGRAM, CONST_PERSISTENT|CONST_CS);
1510 #endif
1511 #ifdef ARES_NI_TCP
1512 REGISTER_LONG_CONSTANT("ARES_NI_TCP", ARES_NI_TCP, CONST_PERSISTENT|CONST_CS);
1513 #endif
1514 #ifdef ARES_NI_UDP
1515 REGISTER_LONG_CONSTANT("ARES_NI_UDP", ARES_NI_UDP, CONST_PERSISTENT|CONST_CS);
1516 #endif
1517 #ifdef ARES_NI_SCTP
1518 REGISTER_LONG_CONSTANT("ARES_NI_SCTP", ARES_NI_SCTP, CONST_PERSISTENT|CONST_CS);
1519 #endif
1520 #ifdef ARES_NI_DCCP
1521 REGISTER_LONG_CONSTANT("ARES_NI_DCCP", ARES_NI_DCCP, CONST_PERSISTENT|CONST_CS);
1522 #endif
1523 #ifdef ARES_NI_NUMERICSCOPE
1524 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSCOPE", ARES_NI_NUMERICSCOPE, CONST_PERSISTENT|CONST_CS);
1525 #endif
1526 #ifdef ARES_NI_LOOKUPHOST
1527 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPHOST", ARES_NI_LOOKUPHOST, CONST_PERSISTENT|CONST_CS);
1528 #endif
1529 #ifdef ARES_NI_LOOKUPSERVICE
1530 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPSERVICE", ARES_NI_LOOKUPSERVICE, CONST_PERSISTENT|CONST_CS);
1531 #endif
1532 #ifdef ARES_NI_IDN
1533 REGISTER_LONG_CONSTANT("ARES_NI_IDN", ARES_NI_IDN, CONST_PERSISTENT|CONST_CS);
1534 #endif
1535 #ifdef ARES_NI_IDN_ALLOW_UNASSIGNED
1536 REGISTER_LONG_CONSTANT("ARES_NI_IDN_ALLOW_UNASSIGNED", ARES_NI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
1537 #endif
1538 #ifdef ARES_NI_IDN_USE_STD
1539 REGISTER_LONG_CONSTANT("ARES_NI_IDN_USE_STD", ARES_NI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
1540 #endif
1541
1542 /*
1543 * Address Info constants
1544 */
1545 #ifdef ARES_AI_CANONNAME
1546 REGISTER_LONG_CONSTANT("ARES_AI_CANONNAME", ARES_AI_CANONNAME, CONST_PERSISTENT|CONST_CS);
1547 #endif
1548 #ifdef ARES_AI_NUMERICHOST
1549 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICHOST", ARES_AI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
1550 #endif
1551 #ifdef ARES_AI_PASSIVE
1552 REGISTER_LONG_CONSTANT("ARES_AI_PASSIVE", ARES_AI_PASSIVE, CONST_PERSISTENT|CONST_CS);
1553 #endif
1554 #ifdef ARES_AI_NUMERICSERV
1555 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICSERV", ARES_AI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
1556 #endif
1557 #ifdef ARES_AI_V
1558 REGISTER_LONG_CONSTANT("ARES_AI_V", ARES_AI_V, CONST_PERSISTENT|CONST_CS);
1559 #endif
1560 #ifdef ARES_AI_ALL
1561 REGISTER_LONG_CONSTANT("ARES_AI_ALL", ARES_AI_ALL, CONST_PERSISTENT|CONST_CS);
1562 #endif
1563 #ifdef ARES_AI_ADDRCONFIG
1564 REGISTER_LONG_CONSTANT("ARES_AI_ADDRCONFIG", ARES_AI_ADDRCONFIG, CONST_PERSISTENT|CONST_CS);
1565 #endif
1566 #ifdef ARES_AI_IDN
1567 REGISTER_LONG_CONSTANT("ARES_AI_IDN", ARES_AI_IDN, CONST_PERSISTENT|CONST_CS);
1568 #endif
1569 #ifdef ARES_AI_IDN_ALLOW_UNASSIGNED
1570 REGISTER_LONG_CONSTANT("ARES_AI_IDN_ALLOW_UNASSIGNED", ARES_AI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
1571 #endif
1572 #ifdef ARES_AI_IDN_USE_STD
1573 REGISTER_LONG_CONSTANT("ARES_AI_IDN_USE_STD", ARES_AI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
1574 #endif
1575 #ifdef ARES_AI_CANONIDN
1576 REGISTER_LONG_CONSTANT("ARES_AI_CANONIDN", ARES_AI_CANONIDN, CONST_PERSISTENT|CONST_CS);
1577 #endif
1578 #ifdef ARES_AI_MASK
1579 REGISTER_LONG_CONSTANT("ARES_AI_MASK", ARES_AI_MASK, CONST_PERSISTENT|CONST_CS);
1580 #endif
1581 #ifdef ARES_GETSOCK_MAXNUM
1582 REGISTER_LONG_CONSTANT("ARES_GETSOCK_MAXNUM", ARES_GETSOCK_MAXNUM, CONST_PERSISTENT|CONST_CS);
1583 #endif
1584
1585 /*
1586 * ns_t (type) constants (arpa/nameser.h)
1587 */
1588
1589 /* (1) Host address. */
1590 REGISTER_LONG_CONSTANT("ARES_T_A", ns_t_a, CONST_CS|CONST_PERSISTENT);
1591 /* (2) Authoritative server. */
1592 REGISTER_LONG_CONSTANT("ARES_T_NS", ns_t_ns, CONST_CS|CONST_PERSISTENT);
1593 /* (3) Mail destination. */
1594 REGISTER_LONG_CONSTANT("ARES_T_MD", ns_t_md, CONST_CS|CONST_PERSISTENT);
1595 /* (4) Mail forwarder. */
1596 REGISTER_LONG_CONSTANT("ARES_T_MF", ns_t_mf, CONST_CS|CONST_PERSISTENT);
1597 /* (5) Canonical name. */
1598 REGISTER_LONG_CONSTANT("ARES_T_CNAME", ns_t_cname, CONST_CS|CONST_PERSISTENT);
1599 /* (6) Start of authority zone. */
1600 REGISTER_LONG_CONSTANT("ARES_T_SOA", ns_t_soa, CONST_CS|CONST_PERSISTENT);
1601 /* (7) Mailbox domain name. */
1602 REGISTER_LONG_CONSTANT("ARES_T_MB", ns_t_mb, CONST_CS|CONST_PERSISTENT);
1603 /* (8) Mail group member. */
1604 REGISTER_LONG_CONSTANT("ARES_T_MG", ns_t_mg, CONST_CS|CONST_PERSISTENT);
1605 /* (9) Mail rename name. */
1606 REGISTER_LONG_CONSTANT("ARES_T_MR", ns_t_mr, CONST_CS|CONST_PERSISTENT);
1607 /* (10) Null resource record. */
1608 REGISTER_LONG_CONSTANT("ARES_T_NULL", ns_t_null, CONST_CS|CONST_PERSISTENT);
1609 /* (11) Well known service. */
1610 REGISTER_LONG_CONSTANT("ARES_T_WKS", ns_t_wks, CONST_CS|CONST_PERSISTENT);
1611 /* (12) Domain name pointer. */
1612 REGISTER_LONG_CONSTANT("ARES_T_PTR", ns_t_ptr, CONST_CS|CONST_PERSISTENT);
1613 /* (13) Host information. */
1614 REGISTER_LONG_CONSTANT("ARES_T_HINFO", ns_t_hinfo, CONST_CS|CONST_PERSISTENT);
1615 /* (14) Mailbox information. */
1616 REGISTER_LONG_CONSTANT("ARES_T_MINFO", ns_t_minfo, CONST_CS|CONST_PERSISTENT);
1617 /* (15) Mail routing information. */
1618 REGISTER_LONG_CONSTANT("ARES_T_MX", ns_t_mx, CONST_CS|CONST_PERSISTENT);
1619 /* (16) Text strings. */
1620 REGISTER_LONG_CONSTANT("ARES_T_TXT", ns_t_txt, CONST_CS|CONST_PERSISTENT);
1621 /* (17) Responsible person. */
1622 REGISTER_LONG_CONSTANT("ARES_T_RP", ns_t_rp, CONST_CS|CONST_PERSISTENT);
1623 /* (18) AFS cell database. */
1624 REGISTER_LONG_CONSTANT("ARES_T_AFSDB", ns_t_afsdb, CONST_CS|CONST_PERSISTENT);
1625 /* (19) X_25 calling address. */
1626 REGISTER_LONG_CONSTANT("ARES_T_X25", ns_t_x25, CONST_CS|CONST_PERSISTENT);
1627 /* (20) ISDN calling address. */
1628 REGISTER_LONG_CONSTANT("ARES_T_ISDN", ns_t_isdn, CONST_CS|CONST_PERSISTENT);
1629 /* (21) Router. */
1630 REGISTER_LONG_CONSTANT("ARES_T_RT", ns_t_rt, CONST_CS|CONST_PERSISTENT);
1631 /* (22) NSAP address. */
1632 REGISTER_LONG_CONSTANT("ARES_T_NSAP", ns_t_nsap, CONST_CS|CONST_PERSISTENT);
1633 /* (23) Reverse NSAP lookup (deprecated). */
1634 /* REGISTER_LONG_CONSTANT("ARES_T_NSAP_PTR", ns_t_nsap_ptr, CONST_CS|CONST_PERSISTENT); */
1635 /* (24) Security signature. */
1636 REGISTER_LONG_CONSTANT("ARES_T_SIG", ns_t_sig, CONST_CS|CONST_PERSISTENT);
1637 /* (25) Security key. */
1638 REGISTER_LONG_CONSTANT("ARES_T_KEY", ns_t_key, CONST_CS|CONST_PERSISTENT);
1639 /* (26) X.400 mail mapping. */
1640 REGISTER_LONG_CONSTANT("ARES_T_PX", ns_t_px, CONST_CS|CONST_PERSISTENT);
1641 /* (27) Geographical position (withdrawn). */
1642 /* REGISTER_LONG_CONSTANT("ARES_T_GPOS", ns_t_gpos, CONST_CS|CONST_PERSISTENT); */
1643 /* (28) Ip6 Address. */
1644 REGISTER_LONG_CONSTANT("ARES_T_AAAA", ns_t_aaaa, CONST_CS|CONST_PERSISTENT);
1645 /* (29) Location Information. */
1646 REGISTER_LONG_CONSTANT("ARES_T_LOC", ns_t_loc, CONST_CS|CONST_PERSISTENT);
1647 /* (30) Next domain (security). */
1648 REGISTER_LONG_CONSTANT("ARES_T_NXT", ns_t_nxt, CONST_CS|CONST_PERSISTENT);
1649 /* (31) Endpoint identifier. */
1650 REGISTER_LONG_CONSTANT("ARES_T_EID", ns_t_eid, CONST_CS|CONST_PERSISTENT);
1651 /* (32) Nimrod Locator. */
1652 REGISTER_LONG_CONSTANT("ARES_T_NIMLOC", ns_t_nimloc, CONST_CS|CONST_PERSISTENT);
1653 /* (33) Server Selection. */
1654 REGISTER_LONG_CONSTANT("ARES_T_SRV", ns_t_srv, CONST_CS|CONST_PERSISTENT);
1655 /* (34) ATM Address */
1656 REGISTER_LONG_CONSTANT("ARES_T_ATMA", ns_t_atma, CONST_CS|CONST_PERSISTENT);
1657 /* (35) Naming Authority PoinTeR */
1658 REGISTER_LONG_CONSTANT("ARES_T_NAPTR", ns_t_naptr, CONST_CS|CONST_PERSISTENT);
1659 /* (36) Key Exchange */
1660 REGISTER_LONG_CONSTANT("ARES_T_KX", ns_t_kx, CONST_CS|CONST_PERSISTENT);
1661 /* (37) Certification record */
1662 REGISTER_LONG_CONSTANT("ARES_T_CERT", ns_t_cert, CONST_CS|CONST_PERSISTENT);
1663 /* (38) IPv6 address (deprecates AAAA) */
1664 REGISTER_LONG_CONSTANT("ARES_T_A6", ns_t_a6, CONST_CS|CONST_PERSISTENT);
1665 /* (39) Non-terminal DNAME (for IPv6) */
1666 REGISTER_LONG_CONSTANT("ARES_T_DNAME", ns_t_dname, CONST_CS|CONST_PERSISTENT);
1667 /* (40) Kitchen sink (experimentatl) */
1668 REGISTER_LONG_CONSTANT("ARES_T_SINK", ns_t_sink, CONST_CS|CONST_PERSISTENT);
1669 /* (41) EDNS0 option (meta-RR) */
1670 REGISTER_LONG_CONSTANT("ARES_T_OPT", ns_t_opt, CONST_CS|CONST_PERSISTENT);
1671 /* (250) Transaction signature. */
1672 REGISTER_LONG_CONSTANT("ARES_T_TSIG", ns_t_tsig, CONST_CS|CONST_PERSISTENT);
1673 /* (251) Incremental zone transfer. */
1674 REGISTER_LONG_CONSTANT("ARES_T_IXFR", ns_t_ixfr, CONST_CS|CONST_PERSISTENT);
1675 /* (252) Transfer zone of authority. */
1676 REGISTER_LONG_CONSTANT("ARES_T_AXFR", ns_t_axfr, CONST_CS|CONST_PERSISTENT);
1677 /* (253) Transfer mailbox records. */
1678 REGISTER_LONG_CONSTANT("ARES_T_MAILB", ns_t_mailb, CONST_CS|CONST_PERSISTENT);
1679 /* (254) Transfer mail agent records. */
1680 REGISTER_LONG_CONSTANT("ARES_T_MAILA", ns_t_maila, CONST_CS|CONST_PERSISTENT);
1681 /* (255) Wildcard match. */
1682 REGISTER_LONG_CONSTANT("ARES_T_ANY", ns_t_any, CONST_CS|CONST_PERSISTENT);
1683
1684 /*
1685 * ns_c (dnsclass) constants (arpa/nameser.h)
1686 */
1687
1688 /* (1) Internet. */
1689 REGISTER_LONG_CONSTANT("ARES_C_IN", ns_c_in, CONST_CS|CONST_PERSISTENT);
1690 /* (2) unallocated/unsupported. */
1691 /* REGISTER_LONG_CONSTANT("ARES_C_2", ns_c_2, CONST_CS|CONST_PERSISTENT); */
1692 /* (3) MIT Chaos-net. */
1693 REGISTER_LONG_CONSTANT("ARES_C_CHAOS", ns_c_chaos, CONST_CS|CONST_PERSISTENT);
1694 /* (4) MIT Hesiod. */
1695 REGISTER_LONG_CONSTANT("ARES_C_HS", ns_c_hs, CONST_CS|CONST_PERSISTENT);
1696 /* (254) for prereq. sections in update requests */
1697 /* REGISTER_LONG_CONSTANT("ARES_C_NONE", ns_c_none, CONST_CS|CONST_PERSISTENT); */
1698 /* (255) Wildcard match. */
1699 REGISTER_LONG_CONSTANT("ARES_C_ANY", ns_c_any, CONST_CS|CONST_PERSISTENT);
1700
1701 le_ares = zend_register_list_destructors_ex(php_ares_le_dtor, NULL, PHP_ARES_LE_NAME, module_number);
1702 le_ares_query = zend_register_list_destructors_ex(php_ares_query_le_dtor, NULL, PHP_ARES_QUERY_LE_NAME, module_number);
1703
1704 return SUCCESS;
1705 }
1706 /* }}} */
1707
1708 /* {{{ PHP_MINFO_FUNCTION */
1709 static PHP_MINFO_FUNCTION(ares)
1710 {
1711 php_info_print_table_start();
1712 php_info_print_table_header(2, "AsyncResolver support", "enabled");
1713 php_info_print_table_end();
1714
1715 php_info_print_table_start();
1716 php_info_print_table_header(3, "Used Library", "compiled", "linked");
1717 php_info_print_table_row(3,
1718 PHP_ARES_LIBNAME,
1719 #ifdef ARES_VERSION_STR
1720 ARES_VERSION_STR,
1721 #else
1722 "unkown",
1723 #endif
1724 #ifdef HAVE_ARES_VERSION
1725 ares_version(NULL)
1726 #else
1727 "unkown"
1728 #endif
1729 );
1730 php_info_print_table_end();
1731 }
1732 /* }}} */
1733
1734 #ifdef ZEND_ENGINE_2
1735 ZEND_BEGIN_ARG_INFO(ai_ares_select, 0)
1736 ZEND_ARG_PASS_INFO(1)
1737 ZEND_ARG_PASS_INFO(1)
1738 ZEND_ARG_PASS_INFO(0)
1739 ZEND_END_ARG_INFO();
1740
1741 ZEND_BEGIN_ARG_INFO(ai_ares_result, 0)
1742 ZEND_ARG_PASS_INFO(0)
1743 ZEND_ARG_PASS_INFO(1)
1744 ZEND_ARG_PASS_INFO(1)
1745 ZEND_END_ARG_INFO();
1746
1747 ZEND_BEGIN_ARG_INFO(ai_ares_fds, 0)
1748 ZEND_ARG_PASS_INFO(0)
1749 ZEND_ARG_PASS_INFO(1)
1750 ZEND_ARG_PASS_INFO(1)
1751 ZEND_END_ARG_INFO();
1752 #else
1753 static unsigned char ai_ares_select[] = {3, BYREF_FORCE, BYREF_FORCE, BYREF_NONE};
1754 static unsigned char ai_ares_result[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
1755 static unsigned char ai_ares_fds[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
1756 #endif
1757
1758 /* {{{ ares_functions[] */
1759 zend_function_entry ares_functions[] = {
1760 #ifdef HAVE_ARES_VERSION
1761 PHP_FE(ares_version, NULL)
1762 #endif
1763 PHP_FE(ares_init, NULL)
1764 PHP_FE(ares_destroy, NULL)
1765 PHP_FE(ares_strerror, NULL)
1766 #ifdef HAVE_ARES_CANCEL
1767 PHP_FE(ares_cancel, NULL)
1768 #endif
1769 PHP_FE(ares_search, NULL)
1770 PHP_FE(ares_query, NULL)
1771 PHP_FE(ares_send, NULL)
1772 PHP_FE(ares_mkquery, NULL)
1773 PHP_FE(ares_gethostbyname, NULL)
1774 PHP_FE(ares_gethostbyaddr, NULL)
1775 #ifdef HAVE_ARES_GETNAMEINFO
1776 PHP_FE(ares_getnameinfo, NULL)
1777 #endif
1778 PHP_FE(ares_result, ai_ares_result)
1779 PHP_FE(ares_packet, NULL)
1780 PHP_FE(ares_process_all, NULL)
1781 PHP_FE(ares_process_once, NULL)
1782 PHP_FE(ares_process, NULL)
1783 PHP_FE(ares_select, ai_ares_select)
1784 PHP_FE(ares_fds, ai_ares_fds)
1785 PHP_FE(ares_timeout, NULL)
1786 PHP_FE(ares_parse_a_reply, NULL)
1787 #ifdef HAVE_ARES_PARSE_AAAA_REPLY
1788 PHP_FE(ares_parse_aaaa_reply, NULL)
1789 #endif
1790 PHP_FE(ares_parse_ptr_reply, NULL)
1791 PHP_FE(ares_expand_name, NULL)
1792 #ifdef HAVE_ARES_EXPAND_STRING
1793 PHP_FE(ares_expand_string, NULL)
1794 #endif
1795 {NULL, NULL, NULL}
1796 };
1797 /* }}} */
1798
1799 /* {{{ ares_module_entry */
1800 zend_module_entry ares_module_entry = {
1801 STANDARD_MODULE_HEADER,
1802 "ares",
1803 ares_functions,
1804 PHP_MINIT(ares),
1805 NULL,
1806 NULL,
1807 NULL,
1808 PHP_MINFO(ares),
1809 NO_VERSION_YET,
1810 STANDARD_MODULE_PROPERTIES
1811 };
1812 /* }}} */
1813
1814 #ifdef COMPILE_DL_ARES
1815 ZEND_GET_MODULE(ares)
1816 #endif
1817
1818 /*
1819 * Local variables:
1820 * tab-width: 4
1821 * c-basic-offset: 4
1822 * End:
1823 * vim600: noet sw=4 ts=4 fdm=marker
1824 * vim<600: noet sw=4 ts=4
1825 */