a0c526bfe298b8bdefca286c6672ac17d4e7c864
[m6w6/ext-ares] / php_ares.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: ares |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2006, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id$ */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 #include "php.h"
20 #include "php_ini.h"
21 #include "php_streams.h"
22 #include "ext/standard/info.h"
23 #include "php_ares.h"
24
25 #include <ares.h>
26 #ifdef HAVE_ARES_VERSION
27 # include <ares_version.h>
28 #endif
29 #ifdef HAVE_NETDB_H
30 # include <netdb.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
35 #ifdef HAVE_ARPA_INET_H
36 # include <arpa/inet.h>
37 #endif
38 #ifdef HAVE_ARPA_NAMESER_H
39 # include <arpa/nameser.h>
40 #endif
41 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
42 # include <arpa/nameser_compat.h>
43 #endif
44
45 #define local static inline
46
47 #ifndef ZEND_ENGINE_2
48 # define PHP_ARES_IS_CALLABLE(a,b,c) 1
49 # ifndef ZTS
50 # undef TSRMLS_SET_CTX
51 # define TSRMLS_SET_CTX
52 # undef TSRMLS_FETCH_FROM_CTX
53 # define TSRMLS_FETCH_FROM_CTX
54 # endif
55 #endif
56 #if (PHP_MAJOR_VERSION > 5) || ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3))
57 # define ADDREF(z) Z_ADDREF_P(z)
58 # define PHP_ARES_IS_CALLABLE(a,b,c) zend_is_callable((a), (b), (c) TSRMLS_CC)
59 #else
60 # define ADDREF(z) ZVAL_ADDREF(z)
61 # define PHP_ARES_IS_CALLABLE(a,b,c) zend_is_callable((a), (b), (c))
62 #endif
63
64 #define PHP_ARES_LE_NAME "AsyncResolver"
65 #define PHP_ARES_QUERY_LE_NAME "AsyncResolverQuery"
66 static int le_ares;
67 static int le_ares_query;
68
69 static const char *php_ares_C_names[] = {
70 "INVALID",
71 "IN",
72 "C2"
73 "CHAOS",
74 "HS", /* 4 */
75 "","","","","","","","","","","","","","","","","","","","", /* 20x */
76 "","","","","","","","","","","","","","","","","","","","", /* 20x */
77 "","","","","","","","","","","","","","","","","","","","", /* 20x */
78 "","","","","","","","","","","","","","","","","","","","", /* 20x */
79 "","","","","","","","","","","","","","","","","","","","", /* 20x */
80 "","","","","","","","","","","","","","","","","","","","", /* 20x */
81 "","","","","","","","","","","","","","","","","","","","", /* 20x */
82 "","","","","","","","","","","","","","","","","","","","", /* 20x */
83 "","","","","","","","","","","","","","","","","","","","", /* 20x */
84 "","","","","","","","","","","","","","","","","","","","", /* 20x */
85 "","","","","","","","","","","","","","","","","","","","", /* 20x */
86 "","","","","","","","","", /* 9x */
87 "NONE", /* 254 */
88 "ANY", /* 255 */
89 };
90
91 static const char *php_ares_T_names[] = {
92 "INVALID",
93 "A",
94 "NS",
95 "MD",
96 "MF",
97 "CNAME",
98 "SOA",
99 "MB",
100 "MG",
101 "MR",
102 "NULL",
103 "WKS",
104 "PTR",
105 "HINFO",
106 "MINFO",
107 "MX",
108 "TXT",
109 "RP",
110 "AFSDB",
111 "X25",
112 "ISDN",
113 "RT",
114 "NSAP",
115 "NSAP_PTR",
116 "SIG",
117 "KEY",
118 "PX",
119 "GPOS",
120 "AAAA",
121 "LOC",
122 "NXT",
123 "EID",
124 "NIMLOC",
125 "SRV",
126 "ATMA",
127 "NAPTR",
128 "KX",
129 "CERT",
130 "A6",
131 "DNAME",
132 "SINK",
133 "OPT",
134 "APL", /* 42 */
135 "","","","","","","","","","","","","","","","","","","","", /* 20x */
136 "","","","","","","","","","","","","","","","","","","","", /* 20x */
137 "","","","","","","","","","","","","","","","","","","","", /* 20x */
138 "","","","","","","","","","","","","","","","","","","","", /* 20x */
139 "","","","","","","","","","","","","","","","","","","","", /* 20x */
140 "","","","","","","","","","","","","","","","","","","","", /* 20x */
141 "","","","","","","","","","","","","","","","","","","","", /* 20x */
142 "","","","","","","","","","","","","","","","","","","","", /* 20x */
143 "","","","","","","","","","","","","","","","","","","","", /* 20x */
144 "","","","","","","","","","","","","","","","","","","","", /* 20x */
145 "","","","","","", /* 6x */
146 "TKEY", /* 249 */
147 "TSIG",
148 "IXFR",
149 "AXFR",
150 "MAILB",
151 "MAILA",
152 "ANY", /* 255 */
153 "ZXFR", /* 256 */
154 };
155
156 #ifdef HAVE_OLD_ARES_STRERROR
157 # define PHP_ARES_ERROR(err) { \
158 char *__tmp = NULL; \
159 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ares_strerror(err, &__tmp)); \
160 if (__tmp) ares_free_errmem(__tmp); \
161 }
162 #else
163 # define PHP_ARES_ERROR(err) \
164 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ares_strerror(err))
165 #endif
166
167 #define RETURN_ARES_ERROR(err) \
168 PHP_ARES_ERROR(err); \
169 RETURN_FALSE
170 #define PHP_ARES_CB_ERROR(param) \
171 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected the " param " argument to be a valid callback")
172 #define RETURN_ARES_CB_ERROR(param) \
173 PHP_ARES_CB_ERROR(param); \
174 RETURN_FALSE
175
176 #define PHP_ARES_QUERY_BUFFER_LEN 2<<0xf
177
178 #ifdef HAVE_ARES_INET_PTON
179 # define inet_pton ares_inet_pton_wrapper
180 static inline int ares_inet_pton_wrapper(int af, const void *src, char *dst, socklen_t size)
181 {
182 return dst == ares_inet_pton(af, src, dst, size);
183 }
184 #endif
185
186 #ifdef HAVE_ARES_INET_NTOP
187 # define inet_ntop ares_inet_ntop
188 #endif
189
190 /* {{{ typedefs */
191 typedef struct _php_ares_options {
192 struct ares_options strct;
193 int flags;
194 } php_ares_options;
195
196 typedef struct _php_ares {
197 ares_channel channel;
198 php_ares_options options;
199 zend_llist queries;
200 void ***tsrm_ls;
201 unsigned in_callback:1;
202 unsigned reserved:31;
203 } php_ares;
204
205 typedef enum _php_ares_query_type {
206 PHP_ARES_CB_STD,
207 PHP_ARES_CB_HOST,
208 PHP_ARES_CB_NINFO,
209 } php_ares_query_type;
210
211 typedef enum _php_ares_query_packet_type {
212 PHP_ARES_PCKT_SEARCH,
213 PHP_ARES_PCKT_QUERY,
214 PHP_ARES_PCKT_SEND,
215 PHP_ARES_PCKT_HNAME,
216 PHP_ARES_PCKT_HADDR,
217 PHP_ARES_PCKT_NINFO,
218 } php_ares_query_packet_type;
219
220 typedef union _php_ares_query_packet_data {
221 struct {
222 char *name;
223 int name_len;
224 long type;
225 long dnsclass;
226 } search;
227 struct {
228 char *name;
229 int name_len;
230 long type;
231 long dnsclass;
232 } query;
233 struct {
234 char *buf;
235 int len;
236 } send;
237 struct {
238 char *name;
239 int name_len;
240 long family;
241 } hname;
242 struct {
243 char *addr;
244 int addr_len;
245 long family;
246 } haddr;
247 struct {
248 char *addr;
249 int addr_len;
250 long port;
251 long family;
252 long flags;
253 } ninfo;
254 } php_ares_query_packet_data;
255
256 typedef struct _php_ares_query_packet {
257 php_ares_query_packet_type type;
258 php_ares_query_packet_data data;
259 } php_ares_query_packet;
260
261 typedef union _php_ares_query_result {
262 struct {
263 zval *arr;
264 char *buf;
265 int len;
266 } std;
267 struct hostent host;
268 struct {
269 char *service;
270 char *node;
271 } ninfo;
272 } php_ares_query_result;
273
274 typedef struct _php_ares_query {
275 int id;
276 int error;
277 php_ares *ares;
278 zval *callback;
279 php_ares_query_type type;
280 php_ares_query_packet packet;
281 php_ares_query_result result;
282 } php_ares_query;
283 /* }}} */
284
285 local struct hostent *php_ares_hostent_ctor(struct hostent *host) /* {{{ */
286 {
287 if (!host) {
288 host = emalloc(sizeof(struct hostent));
289 }
290 memset(host, 0, sizeof(struct hostent));
291
292 return host;
293 }
294 /* }}} */
295
296 local void php_ares_hostent_copy(struct hostent *from, struct hostent *to) /* {{{ */
297 {
298 int i, c;
299 char **ptr;
300
301 memcpy(to, from, sizeof(struct hostent));
302 to->h_name = estrdup(from->h_name);
303 for (c = 0, ptr = from->h_aliases; *ptr; ++ptr, ++c);
304 to->h_aliases = ecalloc((c+1), sizeof(char *));
305 for (i = 0; i < c; ++i) {
306 to->h_aliases[i] = estrdup(from->h_aliases[i]);
307 }
308 for (c = 0, ptr = from->h_addr_list; *ptr; ++ptr, ++c);
309 to->h_addr_list = ecalloc((c+1), sizeof(char *));
310 for (i = 0; i < c; ++i) {
311 to->h_addr_list[i] = emalloc(from->h_length);
312 memcpy(to->h_addr_list[i], from->h_addr_list[i], from->h_length);
313 }
314 }
315 /* }}} */
316
317 local void php_ares_hostent_to_struct(struct hostent *hostent, HashTable *ht) /* {{{ */
318 {
319 zval array, *tmp;
320 char **ptr;
321
322 INIT_PZVAL(&array);
323 Z_TYPE(array) = IS_ARRAY;
324 Z_ARRVAL(array) = ht;
325
326 if (hostent) {
327 add_assoc_string(&array, "name", hostent->h_name, 1);
328
329 MAKE_STD_ZVAL(tmp);
330 array_init(tmp);
331 if (hostent->h_aliases) {
332 for (ptr = hostent->h_aliases; *ptr; ++ptr) {
333 add_next_index_string(tmp, *ptr, 1);
334 }
335 }
336 add_assoc_zval(&array, "aliases", tmp);
337 add_assoc_long(&array, "addrtype", hostent->h_addrtype);
338
339 MAKE_STD_ZVAL(tmp);
340 array_init(tmp);
341 if (hostent->h_addr_list) {
342 for (ptr = hostent->h_addr_list; *ptr; ++ptr) {
343 char name[64] = {0};
344
345 if (inet_ntop(hostent->h_addrtype, *ptr, name, sizeof(name)-1)) {
346 add_next_index_string(tmp, name, 1);
347 }
348 }
349 }
350 add_assoc_zval(&array, "addrlist", tmp);
351 }
352 }
353 /* }}} */
354
355 local void php_ares_hostent_dtor(struct hostent *host) /* {{{ */
356 {
357 char **ptr;
358
359 STR_FREE(host->h_name);
360 if (host->h_aliases) {
361 for (ptr = host->h_aliases; *ptr; ++ptr) {
362 efree(*ptr);
363 }
364 efree(host->h_aliases);
365 }
366 if (host->h_addr_list) {
367 for (ptr = host->h_addr_list; *ptr; ++ptr) {
368 efree(*ptr);
369 }
370 efree(host->h_addr_list);
371 }
372 memset(host, 0, sizeof(struct hostent));
373 }
374 /* }}} */
375
376 local void php_ares_hostent_free(struct hostent **host) /* {{{ */
377 {
378 php_ares_hostent_dtor(*host);
379 efree(*host);
380 *host = NULL;
381 }
382 /* }}} */
383
384 local php_ares_query *php_ares_query_ctor(php_ares_query *query, php_ares_query_type type, php_ares *ares, zval *callback) /* {{{ */
385 {
386 if (!query) {
387 query = emalloc(sizeof(php_ares_query));
388 }
389 memset(query, 0, sizeof(php_ares_query));
390
391 query->ares = ares;
392 query->type = type;
393 query->error = -1;
394
395 if (callback) {
396 ADDREF(callback);
397 query->callback = callback;
398 }
399
400 return query;
401 }
402 /* }}} */
403
404 local void php_ares_query_rsrc(php_ares_query *query, zval *return_value) /* {{{ */
405 {
406 TSRMLS_FETCH_FROM_CTX(query->ares->tsrm_ls);
407
408 ZEND_REGISTER_RESOURCE(return_value, query, le_ares_query);
409 query->id = Z_LVAL_P(return_value);
410 zend_list_addref(query->id);
411 zend_llist_add_element(&query->ares->queries, &query);
412 }
413 /* }}} */
414
415 local void php_ares_query_pckt(php_ares_query *query, php_ares_query_packet_type type, ...)
416 {
417 va_list argv;
418 char *buf;
419 int len;
420
421 va_start(argv, type);
422
423 switch (query->packet.type = type) {
424 case PHP_ARES_PCKT_SEARCH:
425 buf = va_arg(argv, char *);
426 len = va_arg(argv, int);
427 query->packet.data.search.name = estrndup(buf, len);
428 query->packet.data.search.name_len = len;
429 query->packet.data.search.type = va_arg(argv, long);
430 query->packet.data.search.dnsclass = va_arg(argv, long);
431 break;
432
433 case PHP_ARES_PCKT_QUERY:
434 buf = va_arg(argv, char *);
435 len = va_arg(argv, int);
436 query->packet.data.query.name = estrndup(buf, len);
437 query->packet.data.query.name_len = len;
438 query->packet.data.query.type = va_arg(argv, long);
439 query->packet.data.query.dnsclass = va_arg(argv, long);
440 break;
441
442 case PHP_ARES_PCKT_SEND:
443 buf = va_arg(argv, char *);
444 len = va_arg(argv, int);
445 query->packet.data.send.buf = estrndup(buf, len);
446 query->packet.data.send.len = len;
447 break;
448
449 case PHP_ARES_PCKT_HNAME:
450 buf = va_arg(argv, char *);
451 len = va_arg(argv, int);
452 query->packet.data.hname.name = estrndup(buf, len);
453 query->packet.data.hname.name_len = len;
454 query->packet.data.hname.family = va_arg(argv, long);
455 break;
456
457 case PHP_ARES_PCKT_HADDR:
458 buf = va_arg(argv, char *);
459 len = va_arg(argv, int);
460 query->packet.data.haddr.addr = estrndup(buf, len);
461 query->packet.data.haddr.addr_len = len;
462 query->packet.data.haddr.family = va_arg(argv, long);
463 break;
464
465 case PHP_ARES_PCKT_NINFO:
466 query->packet.data.ninfo.flags = va_arg(argv, long);
467 buf = va_arg(argv, char *);
468 len = va_arg(argv, int);
469 query->packet.data.ninfo.addr = estrndup(buf, len);
470 query->packet.data.ninfo.addr_len = len;
471 query->packet.data.ninfo.family = va_arg(argv, long);
472 query->packet.data.ninfo.port = va_arg(argv, long);
473 break;
474 }
475
476 va_end(argv);
477 }
478
479 local void php_ares_query_dtor(php_ares_query *query) /* {{{ */
480 {
481 struct php_ares_query_packet_buf {char *buf;} *packet;
482
483 packet = (struct php_ares_query_packet_buf *) &query->packet.data;
484 if (packet->buf) {
485 efree(packet->buf);
486 }
487 switch (query->type) {
488 case PHP_ARES_CB_STD:
489 if (query->result.std.arr) {
490 zval_ptr_dtor(&query->result.std.arr);
491 }
492 STR_FREE(query->result.std.buf);
493 break;
494 case PHP_ARES_CB_HOST:
495 php_ares_hostent_dtor(&query->result.host);
496 break;
497 case PHP_ARES_CB_NINFO:
498 STR_FREE(query->result.ninfo.service);
499 STR_FREE(query->result.ninfo.node);
500 break;
501 }
502 if (query->callback) {
503 zval_ptr_dtor(&query->callback);
504 }
505 memset(query, 0, sizeof(php_ares_query));
506 }
507 /* }}} */
508
509 local void php_ares_query_free(php_ares_query **query) /* {{{ */
510 {
511 php_ares_query_dtor(*query);
512 efree(*query);
513 *query = NULL;
514 }
515 /* }}} */
516
517 local zend_bool is_numeric(zval **p, long *lval) { /* {{{ */
518 zval *tmp = *p;
519 switch (Z_TYPE_PP(p)) {
520 case IS_STRING:
521 convert_to_long_ex(&tmp);
522 /* no break */
523 case IS_LONG:
524 *lval = Z_LVAL_P(tmp);
525 if (tmp != *p) {
526 zval_ptr_dtor(&tmp);
527 }
528 return !!*lval;
529 }
530 return 0;
531 } /* }}} */
532
533 local php_ares_options *php_ares_options_ctor(php_ares_options *options, HashTable *ht) /* {{{ */
534 {
535 int i;
536 long lval;
537 zval **opt, **entry;
538
539 if (!options) {
540 options = emalloc(sizeof(php_ares_options));
541 }
542 memset(options, 0, sizeof(php_ares_options));
543
544 if (ht && zend_hash_num_elements(ht)) {
545 if ((SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &opt)) && is_numeric(opt, &lval)) {
546 options->flags |= ARES_OPT_FLAGS;
547 options->strct.flags = lval;
548 }
549 #ifdef ARES_OPT_TIMEOUTMS
550 if ((SUCCESS == zend_hash_find(ht, "timeoutms", sizeof("timeoutms"), (void *) &opt)) && is_numeric(opt, &lval)) {
551 options->flags |= ARES_OPT_TIMEOUTMS;
552 options->strct.timeout = lval;
553 } else
554 #endif
555 if ((SUCCESS == zend_hash_find(ht, "timeout", sizeof("timeout"), (void *) &opt)) && is_numeric(opt, &lval)) {
556 options->flags |= ARES_OPT_TIMEOUT;
557 options->strct.timeout = lval;
558 }
559 if ((SUCCESS == zend_hash_find(ht, "tries", sizeof("tries"), (void *) &opt)) && is_numeric(opt, &lval)) {
560 options->flags |= ARES_OPT_TRIES;
561 options->strct.tries = lval;
562 }
563 if ((SUCCESS == zend_hash_find(ht, "ndots", sizeof("ndots"), (void *) &opt)) && is_numeric(opt, &lval)) {
564 options->flags |= ARES_OPT_NDOTS;
565 options->strct.ndots = lval;
566 }
567 if ((SUCCESS == zend_hash_find(ht, "udp_port", sizeof("udp_port"), (void *) &opt)) && is_numeric(opt, &lval)) {
568 options->flags |= ARES_OPT_UDP_PORT;
569 #ifdef PHP_ARES_CARES
570 options->strct.udp_port = (unsigned short) lval;
571 #else
572 options->strct.udp_port = htons((unsigned short) lval);
573 #endif
574 }
575 if ((SUCCESS == zend_hash_find(ht, "tcp_port", sizeof("tcp_port"), (void *) &opt)) && is_numeric(opt, &lval)) {
576 options->flags |= ARES_OPT_TCP_PORT;
577 #ifdef PHP_ARES_CARES
578 options->strct.tcp_port = (unsigned short) lval;
579 #else
580 options->strct.tcp_port = htons((unsigned short) lval);
581 #endif
582 }
583 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)))) {
584 options->strct.servers = ecalloc(i, sizeof(struct in_addr));
585 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt));
586 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(opt), (void *) &entry);
587 zend_hash_move_forward(Z_ARRVAL_PP(opt))) {
588 if (Z_TYPE_PP(entry) == IS_STRING) {
589 inet_pton(AF_INET, Z_STRVAL_PP(entry), &options->strct.servers[options->strct.nservers++]);
590 }
591 }
592 if (options->strct.nservers) {
593 options->flags |= ARES_OPT_SERVERS;
594 }
595 }
596 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)))) {
597 options->strct.domains = ecalloc(i, sizeof(char *));
598 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_PP(opt));
599 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(opt), (void *) &entry);
600 zend_hash_move_forward(Z_ARRVAL_PP(opt))) {
601 if (Z_TYPE_PP(entry) == IS_STRING) {
602 options->strct.domains[options->strct.ndomains++] = estrdup(Z_STRVAL_PP(entry));
603 }
604 }
605 if (options->strct.ndomains) {
606 options->flags |= ARES_OPT_DOMAINS;
607 }
608 }
609 if ((SUCCESS == zend_hash_find(ht, "lookups", sizeof("lookups"), (void *) &opt)) && (Z_TYPE_PP(opt) == IS_STRING)) {
610 options->flags |= ARES_OPT_LOOKUPS;
611 options->strct.lookups = estrdup(Z_STRVAL_PP(opt));
612 }
613 #ifdef ARES_OPT_ROTATE
614 if ((SUCCESS == zend_hash_find(ht, "rotate", sizeof("rotate"), (void *) &opt)) && i_zend_is_true(*opt)) {
615 options->flags |= ARES_OPT_ROTATE;
616 }
617 #endif
618 #ifdef ARES_OPT_EDNSPSZ
619 if ((SUCCESS == zend_hash_find(ht, "ednspsz", sizeof("ednspsz"), (void *) &opt)) && is_numeric(opt, &lval)) {
620 options->flags |= ARES_OPT_EDNSPSZ;
621 options->strct.ednspsz = lval;
622 }
623 #endif
624 }
625
626 return options;
627 }
628 /* }}} */
629
630 local void php_ares_options_dtor(php_ares_options *options) /* {{{ */
631 {
632 int i;
633
634 if (options->strct.servers) {
635 efree(options->strct.servers);
636 }
637
638 if (options->strct.domains) {
639 for (i = 0; i < options->strct.ndomains; ++i) {
640 efree(options->strct.domains[i]);
641 }
642 efree(options->strct.domains);
643 }
644
645 STR_FREE(options->strct.lookups);
646
647 memset(options, 0, sizeof(php_ares_options));
648 }
649 /* }}} */
650
651 local void php_ares_options_free(php_ares_options **options) /* {{{ */
652 {
653 php_ares_options_dtor(*options);
654 efree(*options);
655 *options = NULL;
656 }
657 /* }}} */
658
659 local PHP_ARES_EXPAND_LEN_TYPE php_ares_skip(const unsigned char *pointer, const unsigned char *abuf, int alen TSRMLS_DC)
660 {
661 char *name;
662 int rc;
663 PHP_ARES_EXPAND_LEN_TYPE byte_count;
664
665 /* NOTE: byte_count is not neccessarily the length of the string,
666 i.e. if there were back references */
667 if (ARES_SUCCESS == (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) {
668 /*fprintf(stderr, "-- skipping %s\n", name);*/
669 ares_free_string(name);
670 return byte_count;
671 }
672 PHP_ARES_ERROR(rc);
673 return -1;
674 }
675
676 local int php_ares_parse_record(const unsigned char *abuf, const int alen, const unsigned char **rptr, zval *result TSRMLS_DC)
677 {
678 uint16_t stmp, type, class;
679 uint32_t ltmp, ttl;
680 zval *entry = NULL;
681 PHP_ARES_EXPAND_LEN_TYPE byte_count;
682 const unsigned char *pointer = *rptr;
683 char *name;
684 int rc;
685
686 if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) {
687 return FAILURE;
688 }
689
690 pointer += byte_count;
691
692 MAKE_STD_ZVAL(entry);
693 array_init(entry);
694
695 GETSHORT(type, pointer);
696 add_assoc_string(entry, "type", estrdup(php_ares_T_names[type]), 0);
697 GETSHORT(class, pointer);
698 add_assoc_string(entry, "class", estrdup(php_ares_C_names[class]), 0);
699 GETLONG(ttl, pointer);
700 add_assoc_long(entry, "ttl", ttl);
701 GETSHORT(byte_count, pointer);
702 #if 0
703 fprintf(stderr, ">> processing %s answer of length %d\n", php_ares_T_names[type], byte_count);
704 #endif
705 switch (type) {
706 case T_A:
707 name = ecalloc(1, 16);
708 inet_ntop(AF_INET, pointer, name, 16);
709 add_assoc_string(entry, "addr", name, 0);
710 pointer += byte_count;
711 break;
712 #ifdef T_AAAA
713 case T_AAAA:
714 name = ecalloc(1, 48);
715 inet_ntop(AF_INET6, pointer, name, 48);
716 add_assoc_string(entry, "addr", name, 0);
717 pointer += byte_count;
718 break;
719 #endif
720
721 case T_NS:
722 case T_PTR:
723 case T_CNAME:
724 if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) {
725 PHP_ARES_ERROR(rc);
726 return FAILURE;
727 }
728 pointer += byte_count;
729 add_assoc_string(entry, "name", name, 1);
730 ares_free_string(name);
731 break;
732
733 case T_MX:
734 GETSHORT(stmp, pointer);
735 if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) {
736 PHP_ARES_ERROR(rc);
737 return FAILURE;
738 }
739 pointer += byte_count;
740 add_assoc_long(entry, "weight", stmp);
741 add_assoc_string(entry, "name", name, 1);
742 ares_free_string(name);
743 break;
744
745 case T_SRV:
746 GETSHORT(stmp, pointer);
747 add_assoc_long(entry, "priority", stmp);
748 GETSHORT(stmp, pointer);
749 add_assoc_long(entry, "weight", stmp);
750 GETSHORT(stmp, pointer);
751 add_assoc_long(entry, "port", stmp);
752
753 if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) {
754 PHP_ARES_ERROR(rc);
755 zval_ptr_dtor(&entry);
756 return FAILURE;
757 }
758 pointer += byte_count;
759 add_assoc_string(entry, "name", name, 1);
760 ares_free_string(name);
761 break;
762
763 case T_SOA:
764 if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) {
765 PHP_ARES_ERROR(rc);
766 zval_ptr_dtor(&entry);
767 return FAILURE;
768 }
769 pointer += byte_count;
770 add_assoc_string(entry, "name", name, 1);
771 ares_free_string(name);
772
773 if (ARES_SUCCESS != (rc = ares_expand_name(pointer, abuf, alen, &name, &byte_count))) {
774 PHP_ARES_ERROR(rc);
775 zval_ptr_dtor(&entry);
776 return FAILURE;
777 }
778 pointer += byte_count;
779 add_assoc_string(entry, "mail", name, 1);
780 ares_free_string(name);
781
782 GETLONG(ltmp, pointer);
783 add_assoc_long(entry, "serial", ltmp);
784 GETLONG(ltmp, pointer);
785 add_assoc_long(entry, "refresh", ltmp);
786 GETLONG(ltmp, pointer);
787 add_assoc_long(entry, "retry", ltmp);
788 GETLONG(ltmp, pointer);
789 add_assoc_long(entry, "expire", ltmp);
790 GETLONG(ltmp, pointer);
791 add_assoc_long(entry, "minimum-ttl", ltmp);
792 break;
793
794 case T_TXT:
795 for (ltmp = 0; ltmp < byte_count; ltmp += pointer[ltmp] + 1) {
796 add_next_index_stringl(entry, (const char *) &pointer[ltmp + 1], pointer[ltmp], 1);
797 }
798 pointer += byte_count;
799 break;
800
801 default:
802 #ifndef HAVE_INET_PTON
803 skip:
804 #endif
805 zval_ptr_dtor(&entry);
806 entry = NULL;
807 pointer += byte_count;
808 break;
809 }
810
811 if (entry) {
812 add_next_index_zval(result, entry);
813 }
814 return SUCCESS;
815 }
816
817 local int php_ares_parse(const unsigned char *abuf, int alen, zval *result TSRMLS_DC) /* {{{ */
818 {
819 HEADER *header;
820 PHP_ARES_EXPAND_LEN_TYPE byte_count;
821 const unsigned char *pointer;
822 int query_count, answer_count, auth_count, other_count;
823
824 convert_to_array(result);
825
826 if (!alen || !abuf || !*abuf) {
827 return SUCCESS;
828 }
829
830 header = (HEADER *) abuf;
831 pointer = abuf + HFIXEDSZ;
832
833 for (query_count = ntohs(header->qdcount); query_count--; pointer += byte_count + QFIXEDSZ) {
834 if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) {
835 return FAILURE;
836 }
837 }
838
839 for (answer_count = ntohs(header->ancount); answer_count-- && pointer < (abuf + alen); ) {
840 if (SUCCESS != php_ares_parse_record(abuf, alen, &pointer, result TSRMLS_CC)) {
841 return FAILURE;
842 }
843 }
844
845 for (auth_count = ntohs(header->nscount); auth_count-- && pointer < (abuf + alen); ) {
846 if (SUCCESS != php_ares_parse_record(abuf, alen, &pointer, result TSRMLS_CC)) {
847 return FAILURE;
848 }
849 }
850
851 for (other_count = ntohs(header->arcount); other_count-- && pointer < (abuf + alen); ) {
852 if (SUCCESS != php_ares_parse_record(abuf, alen, &pointer, result TSRMLS_CC)) {
853 return FAILURE;
854 }
855 }
856
857 return SUCCESS;
858 }
859 /* }}} */
860
861 /* {{{ callbacks */
862 static void php_ares_callback_func_old(void *aq, int status, unsigned char *abuf, int alen)
863 {
864 php_ares_query *q = (php_ares_query *) aq;
865 zval *params[4], *retval, *parsed = NULL;
866 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
867
868 q->error = status;
869 if (abuf) {
870 q->result.std.buf = estrndup((char *) abuf, alen);
871 q->result.std.len = alen;
872
873 MAKE_STD_ZVAL(parsed);
874 ZVAL_NULL(parsed);
875 if (SUCCESS == php_ares_parse(abuf, alen, parsed TSRMLS_CC)) {
876 q->result.std.arr = parsed;
877 } else {
878 zval_ptr_dtor(&parsed);
879 parsed = NULL;
880 }
881 }
882
883 if (q->callback) {
884 MAKE_STD_ZVAL(retval);
885 MAKE_STD_ZVAL(params[0]);
886 MAKE_STD_ZVAL(params[1]);
887 MAKE_STD_ZVAL(params[2]);
888 ZVAL_NULL(retval);
889 zend_list_addref(q->id);
890 Z_LVAL_P(params[0]) = q->id;
891 Z_TYPE_P(params[0]) = IS_RESOURCE;
892 ZVAL_LONG(params[1], status);
893 ZVAL_STRINGL(params[2], (char *) abuf, alen, 1);
894
895 if (parsed) {
896 ADDREF(parsed);
897 params[3] = parsed;
898 }
899
900 q->ares->in_callback = 1;
901 call_user_function(EG(function_table), NULL, q->callback, retval, parsed ? 4 : 3, params TSRMLS_CC);
902 q->ares->in_callback = 0;
903
904 zval_ptr_dtor(&retval);
905 zval_ptr_dtor(&params[0]);
906 zval_ptr_dtor(&params[1]);
907 zval_ptr_dtor(&params[2]);
908
909 if (parsed) {
910 zval_ptr_dtor(&params[3]);
911 }
912 }
913 }
914
915 static void php_ares_host_callback_func_old(void *aq, int status, struct hostent *hostent)
916 {
917 php_ares_query *q = (php_ares_query *) aq;
918 zval *params[3], *retval;
919 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
920
921 q->error = status;
922 if (hostent) {
923 php_ares_hostent_copy(hostent, &q->result.host);
924 }
925
926 if (q->callback) {
927 MAKE_STD_ZVAL(retval);
928 MAKE_STD_ZVAL(params[0]);
929 MAKE_STD_ZVAL(params[1]);
930 MAKE_STD_ZVAL(params[2]);
931 ZVAL_NULL(retval);
932 zend_list_addref(q->id);
933 Z_LVAL_P(params[0]) = q->id;
934 Z_TYPE_P(params[0]) = IS_RESOURCE;
935 ZVAL_LONG(params[1], status);
936 object_init(params[2]);
937 php_ares_hostent_to_struct(hostent, HASH_OF(params[2]));
938
939 q->ares->in_callback = 1;
940 call_user_function(EG(function_table), NULL, q->callback, retval, 3, params TSRMLS_CC);
941 q->ares->in_callback = 0;
942
943 zval_ptr_dtor(&retval);
944 zval_ptr_dtor(&params[0]);
945 zval_ptr_dtor(&params[1]);
946 zval_ptr_dtor(&params[2]);
947 }
948 }
949
950 #ifdef HAVE_ARES_GETNAMEINFO
951 static void php_ares_nameinfo_callback_func_old(void *aq, int status, char *node, char *service)
952 {
953 php_ares_query *q = (php_ares_query *) aq;
954 zval *params[4], *retval;
955 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
956
957 q->error = status;
958 if (node) {
959 q->result.ninfo.node = estrdup(node);
960 }
961 if (service) {
962 q->result.ninfo.service = estrdup(service);
963 }
964
965 if (q->callback) {
966 MAKE_STD_ZVAL(retval);
967 MAKE_STD_ZVAL(params[0]);
968 MAKE_STD_ZVAL(params[1]);
969 MAKE_STD_ZVAL(params[2]);
970 MAKE_STD_ZVAL(params[3]);
971 ZVAL_NULL(retval);
972 zend_list_addref(q->id);
973 Z_LVAL_P(params[0]) = q->id;
974 Z_TYPE_P(params[0]) = IS_RESOURCE;
975 ZVAL_LONG(params[1], status);
976 if (node) {
977 ZVAL_STRING(params[2], node, 1);
978 } else {
979 ZVAL_NULL(params[2]);
980 }
981 if (service) {
982 ZVAL_STRING(params[3], service, 1);
983 } else {
984 ZVAL_NULL(params[3]);
985 }
986
987 q->ares->in_callback = 1;
988 call_user_function(EG(function_table), NULL, q->callback, retval, 4, params TSRMLS_CC);
989 q->ares->in_callback = 0;
990
991 zval_ptr_dtor(&retval);
992 zval_ptr_dtor(&params[0]);
993 zval_ptr_dtor(&params[1]);
994 zval_ptr_dtor(&params[2]);
995 zval_ptr_dtor(&params[3]);
996 }
997 }
998 #endif
999
1000 #if PHP_ARES_NEW_CALLBACK_API
1001 # define php_ares_callback_func php_ares_callback_func_new
1002 static void php_ares_callback_func_new(void *aq, int status, int timeouts, unsigned char *abuf, int alen)
1003 {
1004 php_ares_callback_func_old(aq, status, abuf, alen);
1005 }
1006
1007 # define php_ares_host_callback_func php_ares_host_callback_func_new
1008 static void php_ares_host_callback_func_new(void *aq, int status, int timeouts, struct hostent *hostent)
1009 {
1010 php_ares_host_callback_func_old(aq, status, hostent);
1011 }
1012
1013 # ifdef HAVE_ARES_GETNAMEINFO
1014 # define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_new
1015 static void php_ares_nameinfo_callback_func_new(void *aq, int status, int timeouts, char *node, char *service)
1016 {
1017 php_ares_nameinfo_callback_func_old(aq, status, node, service);
1018 }
1019 # endif
1020
1021 #else
1022 # define php_ares_callback_func php_ares_callback_func_old
1023 # define php_ares_host_callback_func php_ares_host_callback_func_old
1024 # ifdef HAVE_ARES_GETNAMEINFO
1025 # define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_old
1026 # endif
1027 #endif
1028 /* }}} */
1029
1030 local struct timeval *php_ares_timeout(php_ares *ares, long max_timeout, struct timeval *tv_buf) /* {{{ */
1031 {
1032 struct timeval maxtv;
1033
1034 if (max_timeout > -1) {
1035 maxtv.tv_sec = max_timeout / 1000;
1036 maxtv.tv_usec = max_timeout % (max_timeout * 1000);
1037 }
1038
1039 return ares_timeout(ares->channel, max_timeout > -1 ? &maxtv : NULL, tv_buf);
1040 }
1041 /* }}} */
1042
1043 local int php_ares_process(php_ares *ares, long max_timeout) /* {{{ */
1044 {
1045 int nfds;
1046 fd_set R, W;
1047 struct timeval tv;
1048
1049 FD_ZERO(&R);
1050 FD_ZERO(&W);
1051
1052 if ((nfds = ares_fds(ares->channel, &R, &W))) {
1053 if (0 < select(nfds, &R, &W, NULL, php_ares_timeout(ares, max_timeout, &tv))) {
1054 ares_process(ares->channel, &R, &W);
1055 }
1056 }
1057
1058 return nfds;
1059 }
1060 /* }}} */
1061
1062 local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w, HashTable *resource_map) /* {{{ */
1063 {
1064 int i, nfds = 0;
1065 zval **fd;
1066
1067 for (i = 0; i < FD_SETSIZE; ++i) {
1068 if (FD_ISSET(i, R)) {
1069 if (resource_map && (SUCCESS == zend_hash_index_find(resource_map, i, (void *) &fd))) {
1070 zval_add_ref(fd);
1071 add_next_index_zval(r, *fd);
1072 } else {
1073 add_next_index_long(r, i);
1074 }
1075 if (i > nfds) {
1076 nfds = i;
1077 }
1078 }
1079 }
1080
1081 for (i = 0; i < FD_SETSIZE; ++i) {
1082 if (FD_ISSET(i, W)) {
1083 if (resource_map && (SUCCESS == zend_hash_index_find(resource_map, i, (void *) &fd))) {
1084 zval_add_ref(fd);
1085 add_next_index_zval(r, *fd);
1086 } else {
1087 add_next_index_long(w, i);
1088 }
1089 if (i > nfds) {
1090 nfds = i;
1091 }
1092 }
1093 }
1094
1095 return nfds ? nfds + 1 : 0;
1096 }
1097 /* }}} */
1098
1099 local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W, HashTable *resource_map TSRMLS_DC) /* {{{ */
1100 {
1101 zval **fd;
1102 int nfds = 0;
1103 zval zmap;
1104
1105 INIT_ZVAL(zmap);
1106 Z_ARRVAL(zmap) = resource_map;
1107 Z_TYPE(zmap) = IS_ARRAY;
1108 if (r && zend_hash_num_elements(Z_ARRVAL_P(r))) {
1109 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(r));
1110 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(r), (void *) &fd);
1111 zend_hash_move_forward(Z_ARRVAL_P(r))) {
1112 if (Z_TYPE_PP(fd) == IS_RESOURCE) {
1113 php_stream *s = NULL;
1114 int id = 0;
1115
1116 ZEND_FETCH_RESOURCE_NO_RETURN(s, php_stream *, fd, -1, NULL, php_file_le_stream());
1117 if (s && (SUCCESS == php_stream_cast(s, PHP_STREAM_AS_FD_FOR_SELECT, (void *) &id, 1))) {
1118 zval_add_ref(fd);
1119 add_index_zval(&zmap, id, *fd);
1120 FD_SET(id, R);
1121 if (id > nfds) {
1122 nfds = id;
1123 }
1124 }
1125 } else if (Z_TYPE_PP(fd) == IS_LONG) {
1126 FD_SET(Z_LVAL_PP(fd), R);
1127 if (Z_LVAL_PP(fd) > nfds) {
1128 nfds = Z_LVAL_PP(fd);
1129 }
1130 }
1131 }
1132 }
1133
1134 if (w && zend_hash_num_elements(Z_ARRVAL_P(w))) {
1135 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(w));
1136 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(w), (void *) &fd);
1137 zend_hash_move_forward(Z_ARRVAL_P(w))) {
1138 if (Z_TYPE_PP(fd) == IS_RESOURCE) {
1139 php_stream *s = NULL;
1140 int id = 0;
1141
1142 ZEND_FETCH_RESOURCE_NO_RETURN(s, php_stream *, fd, -1, NULL, php_file_le_stream());
1143 if (s && (SUCCESS == php_stream_cast(s, PHP_STREAM_AS_FD_FOR_SELECT, (void *) &id, 1))) {
1144 zval_add_ref(fd);
1145 add_index_zval(&zmap, id, *fd);
1146 FD_SET(id, W);
1147 if (id > nfds) {
1148 nfds = id;
1149 }
1150 }
1151 } else if (Z_TYPE_PP(fd) == IS_LONG) {
1152 FD_SET(Z_LVAL_PP(fd), W);
1153 if (Z_LVAL_PP(fd) > nfds) {
1154 nfds = Z_LVAL_PP(fd);
1155 }
1156 }
1157 }
1158 }
1159
1160 return nfds ? nfds + 1 : 0;
1161 }
1162 /* }}} */
1163
1164 static void php_ares_query_llist_dtor(void *entry)
1165 {
1166 php_ares_query *q = *(php_ares_query **) entry;
1167 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
1168 zend_list_delete(q->id);
1169 }
1170
1171 #ifdef HAVE_ARES_VERSION
1172 /* {{{ proto string ares_version()
1173 Get libares version */
1174 static PHP_FUNCTION(ares_version)
1175 {
1176 if (ZEND_NUM_ARGS()) {
1177 WRONG_PARAM_COUNT;
1178 }
1179
1180 RETURN_STRING(estrdup(ares_version(NULL)), 0);
1181 }
1182 /* }}} */
1183 #endif
1184
1185 /* {{{ proto resource ares_init([array options])
1186 Create an ares resource */
1187 static PHP_FUNCTION(ares_init)
1188 {
1189 zval *opt_array = NULL;
1190 php_ares *ares = NULL;
1191 int err;
1192
1193 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opt_array)) {
1194 RETURN_FALSE;
1195 }
1196
1197 ares = ecalloc(1, sizeof(php_ares));
1198 TSRMLS_SET_CTX(ares->tsrm_ls);
1199 zend_llist_init(&ares->queries, sizeof(php_ares_query *), (llist_dtor_func_t) php_ares_query_llist_dtor, 0);
1200 php_ares_options_ctor(&ares->options, opt_array ? Z_ARRVAL_P(opt_array) : NULL);
1201
1202 if (ARES_SUCCESS != (err = ares_init_options(&ares->channel, &ares->options.strct, ares->options.flags))) {
1203 php_ares_options_dtor(&ares->options);
1204 zend_llist_destroy(&ares->queries);
1205 efree(ares);
1206 RETURN_ARES_ERROR(err);
1207 }
1208
1209 ZEND_REGISTER_RESOURCE(return_value, ares, le_ares);
1210 }
1211 /* }}} */
1212
1213 #ifdef HAVE_ARES_SET_LOCAL_DEV
1214 /* {{{ proto void ares_set_local_dev(resource ares, string dev)
1215 Set the local interface name to bind to. */
1216 static PHP_FUNCTION(ares_set_local_dev)
1217 {
1218 zval *rsrc;
1219 char *dev_str = NULL;
1220 int dev_len = 0;
1221 php_ares *ares;
1222
1223 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!", &rsrc, &dev_str, &dev_len)) {
1224 RETURN_FALSE;
1225 }
1226 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1227
1228 ares_set_local_dev(ares->channel, dev_str);
1229 }
1230 #endif
1231
1232 #ifdef HAVE_ARES_SET_LOCAL_IP4
1233 /* {{{ proto void ares_set_local_ip4(resource ares, int addr)
1234 Set the local IPv4 address to bind to. */
1235 static PHP_FUNCTION(ares_set_local_ip4)
1236 {
1237 zval *rsrc;
1238 long ip4_num;
1239 php_ares *ares;
1240
1241 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &rsrc, &ip4_num)) {
1242 RETURN_FALSE;
1243 }
1244 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1245
1246 ares_set_local_ip4(ares->channel, (unsigned int) ip4_num);
1247 }
1248 #endif
1249
1250 #ifdef HAVE_ARES_SET_LOCAL_IP6
1251 /* {{{ proto void ares_set_local_ip6(resource ares, string addr128bit)
1252 Set the local IPv6 address to bind to. */
1253 static PHP_FUNCTION(ares_set_local_ip6)
1254 {
1255 zval *rsrc;
1256 char *ip6_str;
1257 int ip6_len;
1258 php_ares *ares;
1259
1260 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &rsrc, &ip6_str, &ip6_len)) {
1261 RETURN_FALSE;
1262 }
1263 if (16 != ip6_len) {
1264 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Binary IPv6 address string must be exactly 16 bytes long");
1265 }
1266 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1267
1268 ares_set_local_ip6(ares->channel, (unsigned char *) ip6_str);
1269 }
1270 #endif
1271
1272 /* {{{ proto void ares_destroy(resource ares)
1273 Destroy the ares handle */
1274 static PHP_FUNCTION(ares_destroy)
1275 {
1276 zval *rsrc;
1277 php_ares *ares;
1278
1279 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1280 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1281 if (ares->in_callback) {
1282 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy ares handle while in callback");
1283 } else {
1284 zend_list_delete(Z_LVAL_P(rsrc));
1285 }
1286 }
1287 }
1288 /* }}} */
1289
1290 /* {{{ proto string ares_strerror(int status)
1291 Get description of status code */
1292 static PHP_FUNCTION(ares_strerror)
1293 {
1294 long err;
1295 #ifdef HAVE_OLD_ARES_STRERROR
1296 char *__tmp = NULL;
1297 const char *__err;
1298 #endif
1299
1300 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &err)) {
1301 RETURN_FALSE;
1302 }
1303
1304 #ifdef HAVE_OLD_ARES_STRERROR
1305 __err = ares_strerror(err, &__tmp);
1306 RETVAL_STRING(estrdup(__err), 0);
1307 if (__tmp) {
1308 ares_free_errmem(__tmp);
1309 }
1310 #else
1311 RETURN_STRING(estrdup(ares_strerror(err)), 0);
1312 #endif
1313 }
1314 /* }}} */
1315
1316 /* {{{ proto string ares_mkquery(string name, int dnsclass, int type, int id, int rd)
1317 Compose a custom query */
1318 static PHP_FUNCTION(ares_mkquery)
1319 {
1320 char *name_str, *query_str;
1321 int name_len, query_len, err;
1322 long dnsclass, type, id, rd;
1323
1324 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &name_str, &name_len, &dnsclass, &type, &id, &rd)) {
1325 RETURN_FALSE;
1326 }
1327
1328 if (ARES_SUCCESS != (err = ares_mkquery(name_str, dnsclass, type, id, rd, (unsigned char **) &query_str, &query_len))) {
1329 RETURN_ARES_ERROR(err);
1330 }
1331 RETVAL_STRINGL(query_str, query_len, 1);
1332 ares_free_string(query_str);
1333 }
1334 /* }}} */
1335
1336 /* {{{ proto resource ares_search(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
1337 Issue a domain search for name */
1338 static PHP_FUNCTION(ares_search)
1339 {
1340 zval *rsrc, *cb = NULL;
1341 php_ares *ares;
1342 php_ares_query *query;
1343 char *name;
1344 int name_len;
1345 long dnsclass = C_IN, type = T_A;
1346
1347 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
1348 RETURN_FALSE;
1349 }
1350 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1351
1352 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1353 RETURN_ARES_CB_ERROR("second");
1354 }
1355
1356 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1357 php_ares_query_rsrc(query, return_value);
1358 php_ares_query_pckt(query, PHP_ARES_PCKT_SEARCH, name, name_len, type, dnsclass);
1359 ares_search(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
1360 }
1361 /* }}} */
1362
1363 /* {{{ proto resource ares_query(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
1364 Issue a single DNS query */
1365 static PHP_FUNCTION(ares_query)
1366 {
1367 zval *rsrc, *cb = NULL;
1368 php_ares *ares;
1369 php_ares_query *query;
1370 char *name;
1371 int name_len;
1372 long dnsclass = C_IN, type = T_A;
1373
1374 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
1375 RETURN_FALSE;
1376 }
1377 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1378
1379 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1380 RETURN_ARES_CB_ERROR("second");
1381 }
1382
1383 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1384 php_ares_query_rsrc(query, return_value);
1385 php_ares_query_pckt(query, PHP_ARES_PCKT_QUERY, name, name_len, type, dnsclass);
1386 ares_query(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
1387 }
1388 /* }}} */
1389
1390 /* {{{ proto resource ares_send(resource ares, mixed callback, string buf)
1391 Send custom query */
1392 static PHP_FUNCTION(ares_send)
1393 {
1394 zval *rsrc, *cb = NULL;
1395 php_ares *ares;
1396 php_ares_query *query;
1397 char *buf;
1398 int len;
1399
1400 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s", &rsrc, &cb, &buf, &len)) {
1401 RETURN_FALSE;
1402 }
1403 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1404
1405 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1406 RETURN_ARES_CB_ERROR("second");
1407 }
1408
1409 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1410 php_ares_query_rsrc(query, return_value);
1411 php_ares_query_pckt(query, PHP_ARES_PCKT_SEND, buf, len);
1412 ares_send(ares->channel, (const unsigned char *) buf, len, php_ares_callback_func, query);
1413 }
1414 /* }}} */
1415
1416 /* {{{ proto resource ares_gethostbyname(resource ares, mixed callback, string name[, int family = AF_INET])
1417 Get host by name */
1418 static PHP_FUNCTION(ares_gethostbyname)
1419 {
1420 zval *rsrc, *cb = NULL;
1421 php_ares *ares;
1422 php_ares_query *query;
1423 char *name;
1424 int name_len;
1425 long family = AF_INET;
1426
1427 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &name, &name_len, &family)) {
1428 RETURN_FALSE;
1429 }
1430 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1431
1432 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1433 RETURN_ARES_CB_ERROR("second");
1434 }
1435
1436 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
1437 php_ares_query_rsrc(query, return_value);
1438 php_ares_query_pckt(query, PHP_ARES_PCKT_HNAME, name, name_len, family);
1439 ares_gethostbyname(ares->channel, name, family, php_ares_host_callback_func, query);
1440 }
1441 /* }}} */
1442
1443 /* {{{ proto resource ares_gethostbyaddr(resuorce ares, mixed callback, string address[, int family = ARES_AF_INET])
1444 Get host by address */
1445 static PHP_FUNCTION(ares_gethostbyaddr)
1446 {
1447 zval *rsrc, *cb = NULL;
1448 php_ares *ares;
1449 php_ares_query *query;
1450 char *addr;
1451 int addr_len;
1452 long family = AF_INET;
1453 void *sa;
1454 int sa_len;
1455
1456 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &addr, &addr_len, &family)) {
1457 RETURN_FALSE;
1458 }
1459 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1460
1461 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1462 PHP_ARES_CB_ERROR("second");
1463 RETURN_FALSE;
1464 }
1465
1466 switch (family) {
1467 case AF_INET:
1468 sa = emalloc(sa_len = sizeof(struct in_addr));
1469 break;
1470 case AF_INET6:
1471 sa = emalloc(sa_len = sizeof(struct in6_addr));
1472 break;
1473 default:
1474 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither ARES_AF_INET nor ARES_AF_INET6");
1475 RETURN_FALSE;
1476 break;
1477 }
1478
1479 if (1 > inet_pton(family, addr, sa)) {
1480 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1481 RETVAL_FALSE;
1482 } else {
1483 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
1484 php_ares_query_rsrc(query, return_value);
1485 php_ares_query_pckt(query, PHP_ARES_PCKT_HADDR, addr, addr_len, family);
1486 ares_gethostbyaddr(ares->channel, sa, sa_len, family, php_ares_host_callback_func, query);
1487 }
1488 efree(sa);
1489 }
1490 /* }}} */
1491
1492 #ifdef HAVE_ARES_GETNAMEINFO
1493 /* {{{ proto resource ares_getnameinfo(resource ares, mixed callback, int flags, string addr[, int family = ARES_AF_INET[, int port = 0]])
1494 Get name info */
1495 static PHP_FUNCTION(ares_getnameinfo)
1496 {
1497 zval *rsrc, *cb = NULL;
1498 php_ares *ares;
1499 php_ares_query *query;
1500 char *addr;
1501 int addr_len;
1502 long flags, port = 0, family = AF_INET;
1503 struct sockaddr *sa;
1504 struct sockaddr_in *in;
1505 struct sockaddr_in6 *in6;
1506 int sa_len;
1507
1508 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!ls|ll", &rsrc, &cb, &flags, &addr, &addr_len, &family, &port)) {
1509 RETURN_FALSE;
1510 }
1511 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1512
1513 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1514 PHP_ARES_CB_ERROR("second");
1515 RETURN_FALSE;
1516 }
1517
1518 RETVAL_TRUE;
1519 switch (family) {
1520 case AF_INET:
1521 in = ecalloc(1, sa_len = sizeof(struct sockaddr_in));
1522 in->sin_family = AF_INET;
1523 in->sin_port = htons((unsigned short) port);
1524 if (1 > inet_pton(in->sin_family, addr, &in->sin_addr)) {
1525 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1526 RETVAL_FALSE;
1527 }
1528 sa = (struct sockaddr *) in;
1529 break;
1530 case AF_INET6:
1531 in6 = ecalloc(1, sa_len = sizeof(struct sockaddr_in6));
1532 in6->sin6_family = AF_INET6;
1533 in6->sin6_port = htons((unsigned short) port);
1534 if (1 > inet_pton(in6->sin6_family, addr, &in6->sin6_addr)) {
1535 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1536 RETVAL_FALSE;
1537 }
1538 sa = (struct sockaddr *) in6;
1539 break;
1540 default:
1541 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither AF_INET nor AF_INET6");
1542 RETURN_FALSE;
1543 break;
1544 }
1545
1546 if (Z_BVAL_P(return_value)) {
1547 query = php_ares_query_ctor(NULL, PHP_ARES_CB_NINFO, ares, cb);
1548 php_ares_query_rsrc(query, return_value);
1549 php_ares_query_pckt(query, PHP_ARES_PCKT_NINFO, flags, addr, addr_len, family, port);
1550 ares_getnameinfo(ares->channel, sa, sa_len, flags, php_ares_nameinfo_callback_func, query);
1551 }
1552 efree(sa);
1553 }
1554 /* }}} */
1555 #endif
1556
1557 /* {{{ proto mixed ares_result(resource query, int &errno, string &error)
1558 Check a query for its result */
1559 static PHP_FUNCTION(ares_result)
1560 {
1561 zval *rsrc, *zerrno = NULL, *zerror = NULL;
1562 php_ares_query *query;
1563
1564 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &rsrc, &zerrno, &zerror)) {
1565 RETURN_FALSE;
1566 }
1567 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1568
1569 if (zerrno) {
1570 zval_dtor(zerrno);
1571 ZVAL_LONG(zerrno, query->error);
1572 }
1573 if (zerror) {
1574 zval_dtor(zerror);
1575 ZVAL_NULL(zerror);
1576 }
1577
1578 switch (query->error) {
1579 case -1:
1580 RETVAL_FALSE;
1581 break;
1582 default:
1583 if (zerror) {
1584 #ifdef HAVE_OLD_ARES_STRERROR
1585 char *__tmp = NULL;
1586 const char *__err = ares_strerror(query->error, &__tmp);
1587 ZVAL_STRING(zerror, estrdup(__err), 0);
1588 if (__tmp) ares_free_errmem(__tmp);
1589 #else
1590 ZVAL_STRING(zerror, estrdup(ares_strerror(query->error)), 0);
1591 #endif
1592 }
1593 RETVAL_FALSE;
1594 /* no break */
1595 case 0:
1596 switch (query->type) {
1597 case PHP_ARES_CB_STD:
1598 if (query->result.std.arr) {
1599 RETVAL_ZVAL(query->result.std.arr, 1, 0);
1600 } else if (query->result.std.len > 0) {
1601 RETVAL_STRINGL(query->result.std.buf, query->result.std.len, 1);
1602 }
1603 break;
1604 case PHP_ARES_CB_HOST:
1605 if (query->result.host.h_name) {
1606 object_init(return_value);
1607 php_ares_hostent_to_struct(&query->result.host, HASH_OF(return_value));
1608 }
1609 break;
1610 case PHP_ARES_CB_NINFO:
1611 if (query->result.ninfo.node || query->result.ninfo.service) {
1612 object_init(return_value);
1613 add_property_string(return_value, "node", query->result.ninfo.node ? query->result.ninfo.node : "", 1);
1614 add_property_string(return_value, "service", query->result.ninfo.service ? query->result.ninfo.service : "", 1);
1615 }
1616 break;
1617 }
1618 break;
1619 }
1620 }
1621 /* }}} */
1622
1623 /* {{{ proto object ares_packet(resource query)
1624 Check a query for its question packet */
1625 static PHP_FUNCTION(ares_packet)
1626 {
1627 zval *rsrc, *prop;
1628 php_ares_query *query;
1629
1630 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1631 RETURN_FALSE;
1632 }
1633 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1634
1635 object_init(return_value);
1636 add_property_long(return_value, "type", query->packet.type);
1637 add_property_null(return_value, "search");
1638 add_property_null(return_value, "query");
1639 add_property_null(return_value, "send");
1640 add_property_null(return_value, "gethostbyname");
1641 add_property_null(return_value, "gethostbyaddr");
1642 add_property_null(return_value, "getnameinfo");
1643 MAKE_STD_ZVAL(prop);
1644
1645 switch (query->packet.type) {
1646 case PHP_ARES_PCKT_SEARCH:
1647 object_init(prop);
1648 add_property_stringl(prop, "name", query->packet.data.search.name, query->packet.data.search.name_len, 1);
1649 add_property_long(prop, "type", query->packet.data.search.type);
1650 add_property_long(prop, "dnsclass", query->packet.data.search.dnsclass);
1651 add_property_zval(return_value, "search", prop);
1652 break;
1653
1654 case PHP_ARES_PCKT_QUERY:
1655 object_init(prop);
1656 add_property_stringl(prop, "name", query->packet.data.query.name, query->packet.data.query.name_len, 1);
1657 add_property_long(prop, "type", query->packet.data.query.type);
1658 add_property_long(prop, "dnsclass", query->packet.data.query.dnsclass);
1659 add_property_zval(return_value, "query", prop);
1660 break;
1661
1662 case PHP_ARES_PCKT_SEND:
1663 ZVAL_STRINGL(prop, query->packet.data.send.buf, query->packet.data.send.len, 1);
1664 add_property_zval(return_value, "send", prop);
1665 break;
1666
1667 case PHP_ARES_PCKT_HNAME:
1668 object_init(prop);
1669 add_property_stringl(prop, "name", query->packet.data.hname.name, query->packet.data.hname.name_len, 1);
1670 add_property_long(prop, "family", query->packet.data.hname.family);
1671 add_property_zval(return_value, "gethostbyname", prop);
1672 break;
1673
1674 case PHP_ARES_PCKT_HADDR:
1675 object_init(prop);
1676 add_property_stringl(prop, "addr", query->packet.data.haddr.addr, query->packet.data.haddr.addr_len, 1);
1677 add_property_long(prop, "family", query->packet.data.haddr.family);
1678 add_property_zval(return_value, "gethostbyaddr", prop);
1679 break;
1680
1681 case PHP_ARES_PCKT_NINFO:
1682 object_init(prop);
1683 add_property_long(prop, "flags", query->packet.data.ninfo.flags);
1684 add_property_stringl(prop, "addr", query->packet.data.ninfo.addr, query->packet.data.ninfo.addr_len, 1);
1685 add_property_long(prop, "family", query->packet.data.ninfo.family);
1686 add_property_long(prop, "port", query->packet.data.ninfo.port);
1687 add_property_zval(return_value, "getnameinfo", prop);
1688 break;
1689 }
1690
1691 zval_ptr_dtor(&prop);
1692 }
1693 /* }}} */
1694
1695 #ifdef HAVE_ARES_CANCEL
1696 /* {{{ proto void ares_cancel(resource ares)
1697 Cancel pending queries */
1698 static PHP_FUNCTION(ares_cancel)
1699 {
1700 zval *rsrc;
1701 php_ares *ares;
1702
1703 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1704 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1705 ares_cancel(ares->channel);
1706 }
1707 }
1708 /* }}} */
1709 #endif
1710
1711 /* {{{ proto void ares_process_all(resource ares[, int max_timeout_ms])
1712 Process all pending queries */
1713 static PHP_FUNCTION(ares_process_all)
1714 {
1715 zval *rsrc;
1716 php_ares *ares;
1717 long max_timeout = -1;
1718
1719 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1720 RETURN_FALSE;
1721 }
1722 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1723
1724 while (php_ares_process(ares, max_timeout));
1725 }
1726 /* }}} */
1727
1728 /* {{{ proto bool ares_process_once(resource ares[, int max_timout_ms])
1729 Process once and return whether it should be called again */
1730 static PHP_FUNCTION(ares_process_once)
1731 {
1732 zval *rsrc;
1733 php_ares *ares;
1734 long max_timeout = -1;
1735
1736 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1737 RETURN_FALSE;
1738 }
1739 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1740
1741 RETVAL_BOOL(php_ares_process(ares, max_timeout));
1742 }
1743 /* }}} */
1744
1745 /* {{{ proto void ares_process(resource ares, array read, array write)
1746 Process call */
1747 static PHP_FUNCTION(ares_process)
1748 {
1749 zval *rsrc, *read = NULL, *write = NULL;
1750 fd_set R, W;
1751 php_ares *ares;
1752
1753 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a!a!", &rsrc, &read, &write)) {
1754 RETURN_FALSE;
1755 }
1756 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1757
1758 FD_ZERO(&R);
1759 FD_ZERO(&W);
1760
1761 php_ares_extract_fds(read, write, &R, &W, NULL TSRMLS_CC);
1762 ares_process(ares->channel, &R, &W);
1763 }
1764 /* }}} */
1765
1766 /* proto bool ares_select(array &read, array &write, int timeout_ms)
1767 Select call */
1768 static PHP_FUNCTION(ares_select)
1769 {
1770 zval *read = NULL, *write = NULL;
1771 fd_set R, W;
1772 int nfds;
1773 long timeout;
1774 struct timeval tv;
1775 HashTable resource_map;
1776
1777 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aal", &read, &write, &timeout)) {
1778 RETURN_FALSE;
1779 }
1780
1781 if (timeout) {
1782 tv.tv_sec = timeout / 1000;
1783 tv.tv_usec = timeout % (timeout * 1000);
1784 } else {
1785 tv.tv_sec = 1;
1786 tv.tv_usec = 0;
1787 }
1788
1789 FD_ZERO(&R);
1790 FD_ZERO(&W);
1791
1792 zend_hash_init(&resource_map, zend_hash_num_elements(Z_ARRVAL_P(read) + zend_hash_num_elements(Z_ARRVAL_P(write))), NULL, ZVAL_PTR_DTOR, 0);
1793 nfds = php_ares_extract_fds(read, write, &R, &W, &resource_map TSRMLS_CC);
1794 if (-1 < select(nfds, &R, &W, NULL, &tv)) {
1795 zend_hash_clean(Z_ARRVAL_P(read));
1796 zend_hash_clean(Z_ARRVAL_P(write));
1797 php_ares_publish_fds(&R, &W, read, write, &resource_map);
1798 RETVAL_TRUE;
1799 } else {
1800 RETVAL_FALSE;
1801 }
1802 zend_hash_destroy(&resource_map);
1803 }
1804 /* }}} */
1805
1806 /* proto int ares_timeout(resource ares[, int max_timout_ms])
1807 Get suggested select timeout in ms */
1808 static PHP_FUNCTION(ares_timeout)
1809 {
1810 zval *rsrc;
1811 long max_timeout = -1;
1812 struct timeval tv, *tvptr;
1813 php_ares *ares;
1814
1815 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1816 RETURN_FALSE;
1817 }
1818 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1819
1820 if ((tvptr = php_ares_timeout(ares, max_timeout, &tv))) {
1821 RETURN_LONG(tvptr->tv_sec * 1000 + tvptr->tv_usec / 1000);
1822 }
1823 RETURN_LONG(0);
1824 }
1825 /* }}} */
1826
1827 /* {{{ proto int ares_fds(resource ares, array &read, array &write)
1828 Get file descriptors */
1829 static PHP_FUNCTION(ares_fds)
1830 {
1831 zval *rsrc, *read, *write;
1832 fd_set R, W;
1833 php_ares *ares;
1834
1835 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz", &rsrc, &read, &write)) {
1836 RETURN_FALSE;
1837 }
1838 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1839
1840 FD_ZERO(&R);
1841 FD_ZERO(&W);
1842
1843 zval_dtor(read);
1844 zval_dtor(write);
1845 array_init(read);
1846 array_init(write);
1847 ares_fds(ares->channel, &R, &W);
1848 RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write, NULL));
1849 }
1850 /* }}} */
1851
1852 static ZEND_RSRC_DTOR_FUNC(php_ares_le_dtor)
1853 {
1854 php_ares *ares = (php_ares *) rsrc->ptr;
1855
1856 ares_destroy(ares->channel);
1857 zend_llist_destroy(&ares->queries);
1858 php_ares_options_dtor(&ares->options);
1859 efree(ares);
1860 }
1861
1862 static ZEND_RSRC_DTOR_FUNC(php_ares_query_le_dtor)
1863 {
1864 php_ares_query *query = (php_ares_query *) rsrc->ptr;
1865
1866 php_ares_query_dtor(query);
1867 efree(query);
1868 }
1869
1870 /* {{{ PHP_MINIT_FUNCTION */
1871 static PHP_MINIT_FUNCTION(ares)
1872 {
1873 #ifdef HAVE_ARES_LIBRARY_INIT
1874 if (ARES_SUCCESS != ares_library_init(ARES_LIB_INIT_ALL)) {
1875 return FAILURE;
1876 }
1877 #endif
1878 #ifdef HAVE_ARES_VERSION
1879 {
1880 int ares_version_num;
1881 ares_version(&ares_version_num);
1882
1883 REGISTER_LONG_CONSTANT("ARES_VERSION", ares_version_num, CONST_PERSISTENT|CONST_CS);
1884 }
1885 #endif
1886
1887 REGISTER_LONG_CONSTANT("ARES_SUCCESS", ARES_SUCCESS, CONST_PERSISTENT|CONST_CS);
1888 REGISTER_LONG_CONSTANT("ARES_ENODATA", ARES_ENODATA, CONST_PERSISTENT|CONST_CS);
1889 REGISTER_LONG_CONSTANT("ARES_EFORMERR", ARES_EFORMERR, CONST_PERSISTENT|CONST_CS);
1890 REGISTER_LONG_CONSTANT("ARES_ESERVFAIL", ARES_ESERVFAIL, CONST_PERSISTENT|CONST_CS);
1891 REGISTER_LONG_CONSTANT("ARES_ENOTFOUND", ARES_ENOTFOUND, CONST_PERSISTENT|CONST_CS);
1892 REGISTER_LONG_CONSTANT("ARES_ENOTIMP", ARES_ENOTIMP, CONST_PERSISTENT|CONST_CS);
1893 REGISTER_LONG_CONSTANT("ARES_EREFUSED", ARES_EREFUSED, CONST_PERSISTENT|CONST_CS);
1894 REGISTER_LONG_CONSTANT("ARES_EBADQUERY", ARES_EBADQUERY, CONST_PERSISTENT|CONST_CS);
1895 REGISTER_LONG_CONSTANT("ARES_EBADNAME", ARES_EBADNAME, CONST_PERSISTENT|CONST_CS);
1896 REGISTER_LONG_CONSTANT("ARES_EBADFAMILY", ARES_EBADFAMILY, CONST_PERSISTENT|CONST_CS);
1897 REGISTER_LONG_CONSTANT("ARES_EBADRESP", ARES_EBADRESP, CONST_PERSISTENT|CONST_CS);
1898 REGISTER_LONG_CONSTANT("ARES_ECONNREFUSED", ARES_ECONNREFUSED, CONST_PERSISTENT|CONST_CS);
1899 REGISTER_LONG_CONSTANT("ARES_ETIMEOUT", ARES_ETIMEOUT, CONST_PERSISTENT|CONST_CS);
1900 REGISTER_LONG_CONSTANT("ARES_EOF", ARES_EOF, CONST_PERSISTENT|CONST_CS);
1901 REGISTER_LONG_CONSTANT("ARES_EFILE", ARES_EFILE, CONST_PERSISTENT|CONST_CS);
1902 REGISTER_LONG_CONSTANT("ARES_ENOMEM", ARES_ENOMEM, CONST_PERSISTENT|CONST_CS);
1903 REGISTER_LONG_CONSTANT("ARES_EDESTRUCTION", ARES_EDESTRUCTION, CONST_PERSISTENT|CONST_CS);
1904 #ifdef ARES_EBADSTR
1905 REGISTER_LONG_CONSTANT("ARES_EBADSTR", ARES_EBADSTR, CONST_PERSISTENT|CONST_CS);
1906 #endif
1907 #ifdef ARES_EBADFLAGS
1908 REGISTER_LONG_CONSTANT("ARES_EBADFLAGS", ARES_EBADFLAGS, CONST_PERSISTENT|CONST_CS);
1909 #endif
1910 #ifdef ARES_ENONAME
1911 REGISTER_LONG_CONSTANT("ARES_ENONAME", ARES_ENONAME, CONST_PERSISTENT|CONST_CS);
1912 #endif
1913 #ifdef ARES_EBADHINTS
1914 REGISTER_LONG_CONSTANT("ARES_EBADHINTS", ARES_EBADHINTS, CONST_PERSISTENT|CONST_CS);
1915 #endif
1916 #ifdef ARES_ENOTINITIALIZED
1917 REGISTER_LONG_CONSTANT("ARES_ENOTINITIALIZED", ARES_ENOTINITIALIZED, CONST_PERSISTENT|CONST_CS);
1918 #endif
1919 #ifdef ARES_ELOADIPHLPAPI
1920 REGISTER_LONG_CONSTANT("ARES_ELOADIPHLPAPI", ARES_ELOADIPHLPAPI, CONST_PERSISTENT|CONST_CS);
1921 #endif
1922 #ifdef ARES_EADDRGETNETWORKPARAMS
1923 REGISTER_LONG_CONSTANT("ARES_EADDRGETNETWORKPARAMS", ARES_EADDRGETNETWORKPARAMS, CONST_PERSISTENT|CONST_CS);
1924 #endif
1925 #ifdef ARES_ECANCELLED
1926 REGISTER_LONG_CONSTANT("ARES_ECANCELLED", ARES_ECANCELLED, CONST_PERSISTENT|CONST_CS);
1927 #endif
1928
1929 REGISTER_LONG_CONSTANT("ARES_FLAG_USEVC", ARES_FLAG_USEVC, CONST_PERSISTENT|CONST_CS);
1930 REGISTER_LONG_CONSTANT("ARES_FLAG_PRIMARY", ARES_FLAG_PRIMARY, CONST_PERSISTENT|CONST_CS);
1931 REGISTER_LONG_CONSTANT("ARES_FLAG_IGNTC", ARES_FLAG_IGNTC, CONST_PERSISTENT|CONST_CS);
1932 REGISTER_LONG_CONSTANT("ARES_FLAG_NORECURSE", ARES_FLAG_NORECURSE, CONST_PERSISTENT|CONST_CS);
1933 REGISTER_LONG_CONSTANT("ARES_FLAG_STAYOPEN", ARES_FLAG_STAYOPEN, CONST_PERSISTENT|CONST_CS);
1934 REGISTER_LONG_CONSTANT("ARES_FLAG_NOSEARCH", ARES_FLAG_NOSEARCH, CONST_PERSISTENT|CONST_CS);
1935 REGISTER_LONG_CONSTANT("ARES_FLAG_NOALIASES", ARES_FLAG_NOALIASES, CONST_PERSISTENT|CONST_CS);
1936 REGISTER_LONG_CONSTANT("ARES_FLAG_NOCHECKRESP", ARES_FLAG_NOCHECKRESP, CONST_PERSISTENT|CONST_CS);
1937 #ifdef ARES_FLAG_EDNS
1938 REGISTER_LONG_CONSTANT("ARES_FLAG_EDNS", ARES_FLAG_EDNS, CONST_PERSISTENT|CONST_CS);
1939 #endif
1940
1941 /*
1942 * Address Family Constants
1943 */
1944 REGISTER_LONG_CONSTANT("ARES_AF_INET", AF_INET, CONST_PERSISTENT|CONST_CS);
1945 REGISTER_LONG_CONSTANT("ARES_AF_INET6", AF_INET6, CONST_PERSISTENT|CONST_CS);
1946
1947 /*
1948 * Name Info constants
1949 */
1950 #ifdef ARES_NI_NOFQDN
1951 REGISTER_LONG_CONSTANT("ARES_NI_NOFQDN", ARES_NI_NOFQDN, CONST_PERSISTENT|CONST_CS);
1952 #endif
1953 #ifdef ARES_NI_NUMERICHOST
1954 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICHOST", ARES_NI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
1955 #endif
1956 #ifdef ARES_NI_NAMEREQD
1957 REGISTER_LONG_CONSTANT("ARES_NI_NAMEREQD", ARES_NI_NAMEREQD, CONST_PERSISTENT|CONST_CS);
1958 #endif
1959 #ifdef ARES_NI_NUMERICSERV
1960 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSERV", ARES_NI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
1961 #endif
1962 #ifdef ARES_NI_DGRAM
1963 REGISTER_LONG_CONSTANT("ARES_NI_DGRAM", ARES_NI_DGRAM, CONST_PERSISTENT|CONST_CS);
1964 #endif
1965 #ifdef ARES_NI_TCP
1966 REGISTER_LONG_CONSTANT("ARES_NI_TCP", ARES_NI_TCP, CONST_PERSISTENT|CONST_CS);
1967 #endif
1968 #ifdef ARES_NI_UDP
1969 REGISTER_LONG_CONSTANT("ARES_NI_UDP", ARES_NI_UDP, CONST_PERSISTENT|CONST_CS);
1970 #endif
1971 #ifdef ARES_NI_SCTP
1972 REGISTER_LONG_CONSTANT("ARES_NI_SCTP", ARES_NI_SCTP, CONST_PERSISTENT|CONST_CS);
1973 #endif
1974 #ifdef ARES_NI_DCCP
1975 REGISTER_LONG_CONSTANT("ARES_NI_DCCP", ARES_NI_DCCP, CONST_PERSISTENT|CONST_CS);
1976 #endif
1977 #ifdef ARES_NI_NUMERICSCOPE
1978 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSCOPE", ARES_NI_NUMERICSCOPE, CONST_PERSISTENT|CONST_CS);
1979 #endif
1980 #ifdef ARES_NI_LOOKUPHOST
1981 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPHOST", ARES_NI_LOOKUPHOST, CONST_PERSISTENT|CONST_CS);
1982 #endif
1983 #ifdef ARES_NI_LOOKUPSERVICE
1984 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPSERVICE", ARES_NI_LOOKUPSERVICE, CONST_PERSISTENT|CONST_CS);
1985 #endif
1986 #ifdef ARES_NI_IDN
1987 REGISTER_LONG_CONSTANT("ARES_NI_IDN", ARES_NI_IDN, CONST_PERSISTENT|CONST_CS);
1988 #endif
1989 #ifdef ARES_NI_IDN_ALLOW_UNASSIGNED
1990 REGISTER_LONG_CONSTANT("ARES_NI_IDN_ALLOW_UNASSIGNED", ARES_NI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
1991 #endif
1992 #ifdef ARES_NI_IDN_USE_STD
1993 REGISTER_LONG_CONSTANT("ARES_NI_IDN_USE_STD", ARES_NI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
1994 #endif
1995
1996 /*
1997 * Address Info constants
1998 */
1999 #ifdef ARES_AI_CANONNAME
2000 REGISTER_LONG_CONSTANT("ARES_AI_CANONNAME", ARES_AI_CANONNAME, CONST_PERSISTENT|CONST_CS);
2001 #endif
2002 #ifdef ARES_AI_NUMERICHOST
2003 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICHOST", ARES_AI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
2004 #endif
2005 #ifdef ARES_AI_PASSIVE
2006 REGISTER_LONG_CONSTANT("ARES_AI_PASSIVE", ARES_AI_PASSIVE, CONST_PERSISTENT|CONST_CS);
2007 #endif
2008 #ifdef ARES_AI_NUMERICSERV
2009 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICSERV", ARES_AI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
2010 #endif
2011 #ifdef ARES_AI_V
2012 REGISTER_LONG_CONSTANT("ARES_AI_V", ARES_AI_V, CONST_PERSISTENT|CONST_CS);
2013 #endif
2014 #ifdef ARES_AI_ALL
2015 REGISTER_LONG_CONSTANT("ARES_AI_ALL", ARES_AI_ALL, CONST_PERSISTENT|CONST_CS);
2016 #endif
2017 #ifdef ARES_AI_ADDRCONFIG
2018 REGISTER_LONG_CONSTANT("ARES_AI_ADDRCONFIG", ARES_AI_ADDRCONFIG, CONST_PERSISTENT|CONST_CS);
2019 #endif
2020 #ifdef ARES_AI_IDN
2021 REGISTER_LONG_CONSTANT("ARES_AI_IDN", ARES_AI_IDN, CONST_PERSISTENT|CONST_CS);
2022 #endif
2023 #ifdef ARES_AI_IDN_ALLOW_UNASSIGNED
2024 REGISTER_LONG_CONSTANT("ARES_AI_IDN_ALLOW_UNASSIGNED", ARES_AI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
2025 #endif
2026 #ifdef ARES_AI_IDN_USE_STD
2027 REGISTER_LONG_CONSTANT("ARES_AI_IDN_USE_STD", ARES_AI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
2028 #endif
2029 #ifdef ARES_AI_CANONIDN
2030 REGISTER_LONG_CONSTANT("ARES_AI_CANONIDN", ARES_AI_CANONIDN, CONST_PERSISTENT|CONST_CS);
2031 #endif
2032 #ifdef ARES_AI_MASK
2033 REGISTER_LONG_CONSTANT("ARES_AI_MASK", ARES_AI_MASK, CONST_PERSISTENT|CONST_CS);
2034 #endif
2035 #ifdef ARES_GETSOCK_MAXNUM
2036 REGISTER_LONG_CONSTANT("ARES_GETSOCK_MAXNUM", ARES_GETSOCK_MAXNUM, CONST_PERSISTENT|CONST_CS);
2037 #endif
2038
2039 /*
2040 * ns_t (type) constants (arpa/nameser.h)
2041 */
2042 #ifdef T_A
2043 /* (1) Host address. */
2044 REGISTER_LONG_CONSTANT("ARES_T_A", T_A, CONST_CS|CONST_PERSISTENT);
2045 #endif
2046 #ifdef T_NS
2047 /* (2) Authoritative server. */
2048 REGISTER_LONG_CONSTANT("ARES_T_NS", T_NS, CONST_CS|CONST_PERSISTENT);
2049 #endif
2050 #ifdef T_MD
2051 /* (3) Mail destination. */
2052 REGISTER_LONG_CONSTANT("ARES_T_MD", T_MD, CONST_CS|CONST_PERSISTENT);
2053 #endif
2054 #ifdef T_MF
2055 /* (4) Mail forwarder. */
2056 REGISTER_LONG_CONSTANT("ARES_T_MF", T_MF, CONST_CS|CONST_PERSISTENT);
2057 #endif
2058 #ifdef T_CNAME
2059 /* (5) Canonical name. */
2060 REGISTER_LONG_CONSTANT("ARES_T_CNAME", T_CNAME, CONST_CS|CONST_PERSISTENT);
2061 #endif
2062 #ifdef T_SOA
2063 /* (6) Start of authority zone. */
2064 REGISTER_LONG_CONSTANT("ARES_T_SOA", T_SOA, CONST_CS|CONST_PERSISTENT);
2065 #endif
2066 #ifdef T_MB
2067 /* (7) Mailbox domain name. */
2068 REGISTER_LONG_CONSTANT("ARES_T_MB", T_MB, CONST_CS|CONST_PERSISTENT);
2069 #endif
2070 #ifdef T_MG
2071 /* (8) Mail group member. */
2072 REGISTER_LONG_CONSTANT("ARES_T_MG", T_MG, CONST_CS|CONST_PERSISTENT);
2073 #endif
2074 #ifdef T_MR
2075 /* (9) Mail rename name. */
2076 REGISTER_LONG_CONSTANT("ARES_T_MR", T_MR, CONST_CS|CONST_PERSISTENT);
2077 #endif
2078 #ifdef T_NULL
2079 /* (10) Null resource record. */
2080 REGISTER_LONG_CONSTANT("ARES_T_NULL", T_NULL, CONST_CS|CONST_PERSISTENT);
2081 #endif
2082 #ifdef T_WKS
2083 /* (11) Well known service. */
2084 REGISTER_LONG_CONSTANT("ARES_T_WKS", T_WKS, CONST_CS|CONST_PERSISTENT);
2085 #endif
2086 #ifdef T_PTR
2087 /* (12) Domain name pointer. */
2088 REGISTER_LONG_CONSTANT("ARES_T_PTR", T_PTR, CONST_CS|CONST_PERSISTENT);
2089 #endif
2090 #ifdef T_HINFO
2091 /* (13) Host information. */
2092 REGISTER_LONG_CONSTANT("ARES_T_HINFO", T_HINFO, CONST_CS|CONST_PERSISTENT);
2093 #endif
2094 #ifdef T_MINFO
2095 /* (14) Mailbox information. */
2096 REGISTER_LONG_CONSTANT("ARES_T_MINFO", T_MINFO, CONST_CS|CONST_PERSISTENT);
2097 #endif
2098 #ifdef T_MX
2099 /* (15) Mail routing information. */
2100 REGISTER_LONG_CONSTANT("ARES_T_MX", T_MX, CONST_CS|CONST_PERSISTENT);
2101 #endif
2102 #ifdef T_TXT
2103 /* (16) Text strings. */
2104 REGISTER_LONG_CONSTANT("ARES_T_TXT", T_TXT, CONST_CS|CONST_PERSISTENT);
2105 #endif
2106 #ifdef T_RP
2107 /* (17) Responsible person. */
2108 REGISTER_LONG_CONSTANT("ARES_T_RP", T_RP, CONST_CS|CONST_PERSISTENT);
2109 #endif
2110 #ifdef T_AFSDB
2111 /* (18) AFS cell database. */
2112 REGISTER_LONG_CONSTANT("ARES_T_AFSDB", T_AFSDB, CONST_CS|CONST_PERSISTENT);
2113 #endif
2114 #ifdef T_X25
2115 /* (19) X_25 calling address. */
2116 REGISTER_LONG_CONSTANT("ARES_T_X25", T_X25, CONST_CS|CONST_PERSISTENT);
2117 #endif
2118 #ifdef T_ISDN
2119 /* (20) ISDN calling address. */
2120 REGISTER_LONG_CONSTANT("ARES_T_ISDN", T_ISDN, CONST_CS|CONST_PERSISTENT);
2121 #endif
2122 #ifdef T_RT
2123 /* (21) Router. */
2124 REGISTER_LONG_CONSTANT("ARES_T_RT", T_RT, CONST_CS|CONST_PERSISTENT);
2125 #endif
2126 #ifdef T_NSAP
2127 /* (22) NSAP address. */
2128 REGISTER_LONG_CONSTANT("ARES_T_NSAP", T_NSAP, CONST_CS|CONST_PERSISTENT);
2129 #endif
2130 #ifdef T_NSAP_PTR
2131 /* (23) Reverse NSAP lookup (deprecated). */
2132 REGISTER_LONG_CONSTANT("ARES_T_NSAP_PTR", T_NSAP_PTR, CONST_CS|CONST_PERSISTENT);
2133 #endif
2134 #ifdef T_SIG
2135 /* (24) Security signature. */
2136 REGISTER_LONG_CONSTANT("ARES_T_SIG", T_SIG, CONST_CS|CONST_PERSISTENT);
2137 #endif
2138 #ifdef T_KEY
2139 /* (25) Security key. */
2140 REGISTER_LONG_CONSTANT("ARES_T_KEY", T_KEY, CONST_CS|CONST_PERSISTENT);
2141 #endif
2142 #ifdef T_PX
2143 /* (26) X.400 mail mapping. */
2144 REGISTER_LONG_CONSTANT("ARES_T_PX", T_PX, CONST_CS|CONST_PERSISTENT);
2145 #endif
2146 #ifdef T_GPOS
2147 /* (27) Geographical position (withdrawn). */
2148 REGISTER_LONG_CONSTANT("ARES_T_GPOS", T_GPOS, CONST_CS|CONST_PERSISTENT);
2149 #endif
2150 #ifdef T_AAAA
2151 /* (28) Ip6 Address. */
2152 REGISTER_LONG_CONSTANT("ARES_T_AAAA", T_AAAA, CONST_CS|CONST_PERSISTENT);
2153 #endif
2154 #ifdef T_LOC
2155 /* (29) Location Information. */
2156 REGISTER_LONG_CONSTANT("ARES_T_LOC", T_LOC, CONST_CS|CONST_PERSISTENT);
2157 #endif
2158 #ifdef T_NXT
2159 /* (30) Next domain (security). */
2160 REGISTER_LONG_CONSTANT("ARES_T_NXT", T_NXT, CONST_CS|CONST_PERSISTENT);
2161 #endif
2162 #ifdef T_EID
2163 /* (31) Endpoint identifier. */
2164 REGISTER_LONG_CONSTANT("ARES_T_EID", T_EID, CONST_CS|CONST_PERSISTENT);
2165 #endif
2166 #ifdef T_NIMLOC
2167 /* (32) Nimrod Locator. */
2168 REGISTER_LONG_CONSTANT("ARES_T_NIMLOC", T_NIMLOC, CONST_CS|CONST_PERSISTENT);
2169 #endif
2170 #ifdef T_SRV
2171 /* (33) Server Selection. */
2172 REGISTER_LONG_CONSTANT("ARES_T_SRV", T_SRV, CONST_CS|CONST_PERSISTENT);
2173 #endif
2174 #ifdef T_ATMA
2175 /* (34) ATM Address */
2176 REGISTER_LONG_CONSTANT("ARES_T_ATMA", T_ATMA, CONST_CS|CONST_PERSISTENT);
2177 #endif
2178 #ifdef T_NAPTR
2179 /* (35) Naming Authority Pointer */
2180 REGISTER_LONG_CONSTANT("ARES_T_NAPTR", T_NAPTR, CONST_CS|CONST_PERSISTENT);
2181 #endif
2182 #ifdef T_KX
2183 /* (36) Key Exchange */
2184 REGISTER_LONG_CONSTANT("ARES_T_KX", T_KX, CONST_CS|CONST_PERSISTENT);
2185 #endif
2186 #ifdef T_CERT
2187 /* (37) Certification record */
2188 REGISTER_LONG_CONSTANT("ARES_T_CERT", T_CERT, CONST_CS|CONST_PERSISTENT);
2189 #endif
2190 #ifdef T_A6
2191 /* (38) IPv6 address (deprecates AAAA) */
2192 REGISTER_LONG_CONSTANT("ARES_T_A6", T_A6, CONST_CS|CONST_PERSISTENT);
2193 #endif
2194 #ifdef T_DNAME
2195 /* (39) Non-terminal DNAME (for IPv6) */
2196 REGISTER_LONG_CONSTANT("ARES_T_DNAME", T_DNAME, CONST_CS|CONST_PERSISTENT);
2197 #endif
2198 #ifdef T_SINK
2199 /* (40) Kitchen sink (experimentatl) */
2200 REGISTER_LONG_CONSTANT("ARES_T_SINK", T_SINK, CONST_CS|CONST_PERSISTENT);
2201 #endif
2202 #ifdef T_OPT
2203 /* (41) EDNS0 option (meta-RR) */
2204 REGISTER_LONG_CONSTANT("ARES_T_OPT", T_OPT, CONST_CS|CONST_PERSISTENT);
2205 #endif
2206 #ifdef T_TSIG
2207 /* (250) Transaction signature. */
2208 REGISTER_LONG_CONSTANT("ARES_T_TSIG", T_TSIG, CONST_CS|CONST_PERSISTENT);
2209 #endif
2210 #ifdef T_IXFR
2211 /* (251) Incremental zone transfer. */
2212 REGISTER_LONG_CONSTANT("ARES_T_IXFR", T_IXFR, CONST_CS|CONST_PERSISTENT);
2213 #endif
2214 #ifdef T_AXFR
2215 /* (252) Transfer zone of authority. */
2216 REGISTER_LONG_CONSTANT("ARES_T_AXFR", T_AXFR, CONST_CS|CONST_PERSISTENT);
2217 #endif
2218 #ifdef T_MAILB
2219 /* (253) Transfer mailbox records. */
2220 REGISTER_LONG_CONSTANT("ARES_T_MAILB", T_MAILB, CONST_CS|CONST_PERSISTENT);
2221 #endif
2222 #ifdef T_MAILA
2223 /* (254) Transfer mail agent records. */
2224 REGISTER_LONG_CONSTANT("ARES_T_MAILA", T_MAILA, CONST_CS|CONST_PERSISTENT);
2225 #endif
2226 #ifdef T_ANY
2227 /* (255) Wildcard match. */
2228 REGISTER_LONG_CONSTANT("ARES_T_ANY", T_ANY, CONST_CS|CONST_PERSISTENT);
2229 #endif
2230
2231 /*
2232 * ns_c (dnsclass) constants (arpa/nameser.h)
2233 */
2234
2235 #ifdef C_IN
2236 /* (1) Internet. */
2237 REGISTER_LONG_CONSTANT("ARES_C_IN", C_IN, CONST_CS|CONST_PERSISTENT);
2238 #endif
2239 #ifdef C_2
2240 /* (2) unallocated/unsupported. */
2241 REGISTER_LONG_CONSTANT("ARES_C_2", C_2, CONST_CS|CONST_PERSISTENT);
2242 #endif
2243 #ifdef C_CHAOS
2244 /* (3) MIT Chaos-net. */
2245 REGISTER_LONG_CONSTANT("ARES_C_CHAOS", C_CHAOS, CONST_CS|CONST_PERSISTENT);
2246 #endif
2247 #ifdef C_HS
2248 /* (4) MIT Hesiod. */
2249 REGISTER_LONG_CONSTANT("ARES_C_HS", C_HS, CONST_CS|CONST_PERSISTENT);
2250 #endif
2251 #ifdef C_NONE
2252 /* (254) for prereq. sections in update requests */
2253 REGISTER_LONG_CONSTANT("ARES_C_NONE", C_NONE, CONST_CS|CONST_PERSISTENT);
2254 #endif
2255 #ifdef C_ANY
2256 /* (255) Wildcard match. */
2257 REGISTER_LONG_CONSTANT("ARES_C_ANY", C_ANY, CONST_CS|CONST_PERSISTENT);
2258 #endif
2259
2260 le_ares = zend_register_list_destructors_ex(php_ares_le_dtor, NULL, PHP_ARES_LE_NAME, module_number);
2261 le_ares_query = zend_register_list_destructors_ex(php_ares_query_le_dtor, NULL, PHP_ARES_QUERY_LE_NAME, module_number);
2262
2263 return SUCCESS;
2264 }
2265 /* }}} */
2266
2267 /* {{{ PHP_MSHUTDOWN_FUNCTION */
2268 static PHP_MSHUTDOWN_FUNCTION(ares)
2269 {
2270 #ifdef HAVE_ARES_LIBRARY_CLEANUP
2271 ares_library_cleanup();
2272 #endif
2273 return SUCCESS;
2274 }
2275 /* }}} */
2276
2277 /* {{{ PHP_MINFO_FUNCTION */
2278 static PHP_MINFO_FUNCTION(ares)
2279 {
2280 php_info_print_table_start();
2281 php_info_print_table_header(2, "AsyncResolver support", "enabled");
2282 php_info_print_table_row(2, "Version", PHP_ARES_VERSION);
2283 php_info_print_table_end();
2284
2285 php_info_print_table_start();
2286 php_info_print_table_header(3, "Used Library", "compiled", "linked");
2287 php_info_print_table_row(3,
2288 PHP_ARES_LIBNAME,
2289 #ifdef ARES_VERSION_STR
2290 ARES_VERSION_STR,
2291 #else
2292 "unkown",
2293 #endif
2294 #ifdef HAVE_ARES_VERSION
2295 ares_version(NULL)
2296 #else
2297 "unkown"
2298 #endif
2299 );
2300 php_info_print_table_end();
2301 }
2302 /* }}} */
2303
2304 #ifdef ZEND_ENGINE_2
2305 ZEND_BEGIN_ARG_INFO(ai_ares_select, 0)
2306 ZEND_ARG_PASS_INFO(1)
2307 ZEND_ARG_PASS_INFO(1)
2308 ZEND_ARG_PASS_INFO(0)
2309 ZEND_END_ARG_INFO();
2310
2311 ZEND_BEGIN_ARG_INFO(ai_ares_result, 0)
2312 ZEND_ARG_PASS_INFO(0)
2313 ZEND_ARG_PASS_INFO(1)
2314 ZEND_ARG_PASS_INFO(1)
2315 ZEND_END_ARG_INFO();
2316
2317 ZEND_BEGIN_ARG_INFO(ai_ares_fds, 0)
2318 ZEND_ARG_PASS_INFO(0)
2319 ZEND_ARG_PASS_INFO(1)
2320 ZEND_ARG_PASS_INFO(1)
2321 ZEND_END_ARG_INFO();
2322 #else
2323 static unsigned char ai_ares_select[] = {3, BYREF_FORCE, BYREF_FORCE, BYREF_NONE};
2324 static unsigned char ai_ares_result[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
2325 static unsigned char ai_ares_fds[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
2326 #endif
2327
2328 /* {{{ ares_functions[] */
2329 zend_function_entry ares_functions[] = {
2330 #ifdef HAVE_ARES_VERSION
2331 PHP_FE(ares_version, NULL)
2332 #endif
2333 PHP_FE(ares_init, NULL)
2334 PHP_FE(ares_destroy, NULL)
2335 PHP_FE(ares_strerror, NULL)
2336 #ifdef HAVE_ARES_CANCEL
2337 PHP_FE(ares_cancel, NULL)
2338 #endif
2339 PHP_FE(ares_search, NULL)
2340 PHP_FE(ares_query, NULL)
2341 PHP_FE(ares_send, NULL)
2342 PHP_FE(ares_mkquery, NULL)
2343 PHP_FE(ares_gethostbyname, NULL)
2344 PHP_FE(ares_gethostbyaddr, NULL)
2345 #ifdef HAVE_ARES_GETNAMEINFO
2346 PHP_FE(ares_getnameinfo, NULL)
2347 #endif
2348 PHP_FE(ares_result, ai_ares_result)
2349 PHP_FE(ares_packet, NULL)
2350 PHP_FE(ares_process_all, NULL)
2351 PHP_FE(ares_process_once, NULL)
2352 PHP_FE(ares_process, NULL)
2353 PHP_FE(ares_select, ai_ares_select)
2354 PHP_FE(ares_fds, ai_ares_fds)
2355 PHP_FE(ares_timeout, NULL)
2356 #ifdef HAVE_ARES_SET_LOCAL_DEV
2357 PHP_FE(ares_set_local_dev, NULL)
2358 #endif
2359 #ifdef HAVE_ARES_SET_LOCAL_IP4
2360 PHP_FE(ares_set_local_ip4, NULL)
2361 #endif
2362 #ifdef HAVE_ARES_SET_LOCAL_IP6
2363 PHP_FE(ares_set_local_ip6, NULL)
2364 #endif
2365 {NULL, NULL, NULL}
2366 };
2367 /* }}} */
2368
2369 /* {{{ ares_module_entry */
2370 zend_module_entry ares_module_entry = {
2371 STANDARD_MODULE_HEADER,
2372 "ares",
2373 ares_functions,
2374 PHP_MINIT(ares),
2375 PHP_MSHUTDOWN(ares),
2376 NULL,
2377 NULL,
2378 PHP_MINFO(ares),
2379 PHP_ARES_VERSION,
2380 STANDARD_MODULE_PROPERTIES
2381 };
2382 /* }}} */
2383
2384 #ifdef COMPILE_DL_ARES
2385 ZEND_GET_MODULE(ares)
2386 #endif
2387
2388 /*
2389 * Local variables:
2390 * tab-width: 4
2391 * c-basic-offset: 4
2392 * End:
2393 * vim600: noet sw=4 ts=4 fdm=marker
2394 * vim<600: noet sw=4 ts=4
2395 */