fix pointer advancement
[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 *rptr = pointer;
815 return SUCCESS;
816 }
817
818 local int php_ares_parse(const unsigned char *abuf, int alen, zval *result TSRMLS_DC) /* {{{ */
819 {
820 HEADER *header;
821 PHP_ARES_EXPAND_LEN_TYPE byte_count;
822 const unsigned char *pointer;
823 int query_count, answer_count, auth_count, other_count;
824
825 convert_to_array(result);
826
827 if (!alen || !abuf || !*abuf) {
828 return SUCCESS;
829 }
830
831 header = (HEADER *) abuf;
832 pointer = abuf + HFIXEDSZ;
833
834 for (query_count = ntohs(header->qdcount); query_count--; pointer += byte_count + QFIXEDSZ) {
835 if (0 > (byte_count = php_ares_skip(pointer, abuf, alen TSRMLS_CC))) {
836 return FAILURE;
837 }
838 }
839
840 for (answer_count = ntohs(header->ancount); answer_count-- && pointer < (abuf + alen); ) {
841 if (SUCCESS != php_ares_parse_record(abuf, alen, &pointer, result TSRMLS_CC)) {
842 return FAILURE;
843 }
844 }
845
846 for (auth_count = ntohs(header->nscount); auth_count-- && pointer < (abuf + alen); ) {
847 if (SUCCESS != php_ares_parse_record(abuf, alen, &pointer, result TSRMLS_CC)) {
848 return FAILURE;
849 }
850 }
851
852 for (other_count = ntohs(header->arcount); other_count-- && pointer < (abuf + alen); ) {
853 if (SUCCESS != php_ares_parse_record(abuf, alen, &pointer, result TSRMLS_CC)) {
854 return FAILURE;
855 }
856 }
857
858 return SUCCESS;
859 }
860 /* }}} */
861
862 /* {{{ callbacks */
863 static void php_ares_callback_func_old(void *aq, int status, unsigned char *abuf, int alen)
864 {
865 php_ares_query *q = (php_ares_query *) aq;
866 zval *params[4], *retval, *parsed = NULL;
867 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
868
869 q->error = status;
870 if (abuf) {
871 q->result.std.buf = estrndup((char *) abuf, alen);
872 q->result.std.len = alen;
873
874 MAKE_STD_ZVAL(parsed);
875 ZVAL_NULL(parsed);
876 if (SUCCESS == php_ares_parse(abuf, alen, parsed TSRMLS_CC)) {
877 q->result.std.arr = parsed;
878 } else {
879 zval_ptr_dtor(&parsed);
880 parsed = NULL;
881 }
882 }
883
884 if (q->callback) {
885 MAKE_STD_ZVAL(retval);
886 MAKE_STD_ZVAL(params[0]);
887 MAKE_STD_ZVAL(params[1]);
888 MAKE_STD_ZVAL(params[2]);
889 ZVAL_NULL(retval);
890 zend_list_addref(q->id);
891 Z_LVAL_P(params[0]) = q->id;
892 Z_TYPE_P(params[0]) = IS_RESOURCE;
893 ZVAL_LONG(params[1], status);
894 ZVAL_STRINGL(params[2], (char *) abuf, alen, 1);
895
896 if (parsed) {
897 ADDREF(parsed);
898 params[3] = parsed;
899 }
900
901 q->ares->in_callback = 1;
902 call_user_function(EG(function_table), NULL, q->callback, retval, parsed ? 4 : 3, params TSRMLS_CC);
903 q->ares->in_callback = 0;
904
905 zval_ptr_dtor(&retval);
906 zval_ptr_dtor(&params[0]);
907 zval_ptr_dtor(&params[1]);
908 zval_ptr_dtor(&params[2]);
909
910 if (parsed) {
911 zval_ptr_dtor(&params[3]);
912 }
913 }
914 }
915
916 static void php_ares_host_callback_func_old(void *aq, int status, struct hostent *hostent)
917 {
918 php_ares_query *q = (php_ares_query *) aq;
919 zval *params[3], *retval;
920 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
921
922 q->error = status;
923 if (hostent) {
924 php_ares_hostent_copy(hostent, &q->result.host);
925 }
926
927 if (q->callback) {
928 MAKE_STD_ZVAL(retval);
929 MAKE_STD_ZVAL(params[0]);
930 MAKE_STD_ZVAL(params[1]);
931 MAKE_STD_ZVAL(params[2]);
932 ZVAL_NULL(retval);
933 zend_list_addref(q->id);
934 Z_LVAL_P(params[0]) = q->id;
935 Z_TYPE_P(params[0]) = IS_RESOURCE;
936 ZVAL_LONG(params[1], status);
937 object_init(params[2]);
938 php_ares_hostent_to_struct(hostent, HASH_OF(params[2]));
939
940 q->ares->in_callback = 1;
941 call_user_function(EG(function_table), NULL, q->callback, retval, 3, params TSRMLS_CC);
942 q->ares->in_callback = 0;
943
944 zval_ptr_dtor(&retval);
945 zval_ptr_dtor(&params[0]);
946 zval_ptr_dtor(&params[1]);
947 zval_ptr_dtor(&params[2]);
948 }
949 }
950
951 #ifdef HAVE_ARES_GETNAMEINFO
952 static void php_ares_nameinfo_callback_func_old(void *aq, int status, char *node, char *service)
953 {
954 php_ares_query *q = (php_ares_query *) aq;
955 zval *params[4], *retval;
956 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
957
958 q->error = status;
959 if (node) {
960 q->result.ninfo.node = estrdup(node);
961 }
962 if (service) {
963 q->result.ninfo.service = estrdup(service);
964 }
965
966 if (q->callback) {
967 MAKE_STD_ZVAL(retval);
968 MAKE_STD_ZVAL(params[0]);
969 MAKE_STD_ZVAL(params[1]);
970 MAKE_STD_ZVAL(params[2]);
971 MAKE_STD_ZVAL(params[3]);
972 ZVAL_NULL(retval);
973 zend_list_addref(q->id);
974 Z_LVAL_P(params[0]) = q->id;
975 Z_TYPE_P(params[0]) = IS_RESOURCE;
976 ZVAL_LONG(params[1], status);
977 if (node) {
978 ZVAL_STRING(params[2], node, 1);
979 } else {
980 ZVAL_NULL(params[2]);
981 }
982 if (service) {
983 ZVAL_STRING(params[3], service, 1);
984 } else {
985 ZVAL_NULL(params[3]);
986 }
987
988 q->ares->in_callback = 1;
989 call_user_function(EG(function_table), NULL, q->callback, retval, 4, params TSRMLS_CC);
990 q->ares->in_callback = 0;
991
992 zval_ptr_dtor(&retval);
993 zval_ptr_dtor(&params[0]);
994 zval_ptr_dtor(&params[1]);
995 zval_ptr_dtor(&params[2]);
996 zval_ptr_dtor(&params[3]);
997 }
998 }
999 #endif
1000
1001 #if PHP_ARES_NEW_CALLBACK_API
1002 # define php_ares_callback_func php_ares_callback_func_new
1003 static void php_ares_callback_func_new(void *aq, int status, int timeouts, unsigned char *abuf, int alen)
1004 {
1005 php_ares_callback_func_old(aq, status, abuf, alen);
1006 }
1007
1008 # define php_ares_host_callback_func php_ares_host_callback_func_new
1009 static void php_ares_host_callback_func_new(void *aq, int status, int timeouts, struct hostent *hostent)
1010 {
1011 php_ares_host_callback_func_old(aq, status, hostent);
1012 }
1013
1014 # ifdef HAVE_ARES_GETNAMEINFO
1015 # define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_new
1016 static void php_ares_nameinfo_callback_func_new(void *aq, int status, int timeouts, char *node, char *service)
1017 {
1018 php_ares_nameinfo_callback_func_old(aq, status, node, service);
1019 }
1020 # endif
1021
1022 #else
1023 # define php_ares_callback_func php_ares_callback_func_old
1024 # define php_ares_host_callback_func php_ares_host_callback_func_old
1025 # ifdef HAVE_ARES_GETNAMEINFO
1026 # define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_old
1027 # endif
1028 #endif
1029 /* }}} */
1030
1031 local struct timeval *php_ares_timeout(php_ares *ares, long max_timeout, struct timeval *tv_buf) /* {{{ */
1032 {
1033 struct timeval maxtv;
1034
1035 if (max_timeout > -1) {
1036 maxtv.tv_sec = max_timeout / 1000;
1037 maxtv.tv_usec = max_timeout % (max_timeout * 1000);
1038 }
1039
1040 return ares_timeout(ares->channel, max_timeout > -1 ? &maxtv : NULL, tv_buf);
1041 }
1042 /* }}} */
1043
1044 local int php_ares_process(php_ares *ares, long max_timeout) /* {{{ */
1045 {
1046 int nfds;
1047 fd_set R, W;
1048 struct timeval tv;
1049
1050 FD_ZERO(&R);
1051 FD_ZERO(&W);
1052
1053 if ((nfds = ares_fds(ares->channel, &R, &W))) {
1054 if (0 < select(nfds, &R, &W, NULL, php_ares_timeout(ares, max_timeout, &tv))) {
1055 ares_process(ares->channel, &R, &W);
1056 }
1057 }
1058
1059 return nfds;
1060 }
1061 /* }}} */
1062
1063 local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w, HashTable *resource_map) /* {{{ */
1064 {
1065 int i, nfds = 0;
1066 zval **fd;
1067
1068 for (i = 0; i < FD_SETSIZE; ++i) {
1069 if (FD_ISSET(i, R)) {
1070 if (resource_map && (SUCCESS == zend_hash_index_find(resource_map, i, (void *) &fd))) {
1071 zval_add_ref(fd);
1072 add_next_index_zval(r, *fd);
1073 } else {
1074 add_next_index_long(r, i);
1075 }
1076 if (i > nfds) {
1077 nfds = i;
1078 }
1079 }
1080 }
1081
1082 for (i = 0; i < FD_SETSIZE; ++i) {
1083 if (FD_ISSET(i, W)) {
1084 if (resource_map && (SUCCESS == zend_hash_index_find(resource_map, i, (void *) &fd))) {
1085 zval_add_ref(fd);
1086 add_next_index_zval(r, *fd);
1087 } else {
1088 add_next_index_long(w, i);
1089 }
1090 if (i > nfds) {
1091 nfds = i;
1092 }
1093 }
1094 }
1095
1096 return nfds ? nfds + 1 : 0;
1097 }
1098 /* }}} */
1099
1100 local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W, HashTable *resource_map TSRMLS_DC) /* {{{ */
1101 {
1102 zval **fd;
1103 int nfds = 0;
1104 zval zmap;
1105
1106 INIT_ZVAL(zmap);
1107 Z_ARRVAL(zmap) = resource_map;
1108 Z_TYPE(zmap) = IS_ARRAY;
1109 if (r && zend_hash_num_elements(Z_ARRVAL_P(r))) {
1110 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(r));
1111 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(r), (void *) &fd);
1112 zend_hash_move_forward(Z_ARRVAL_P(r))) {
1113 if (Z_TYPE_PP(fd) == IS_RESOURCE) {
1114 php_stream *s = NULL;
1115 int id = 0;
1116
1117 ZEND_FETCH_RESOURCE_NO_RETURN(s, php_stream *, fd, -1, NULL, php_file_le_stream());
1118 if (s && (SUCCESS == php_stream_cast(s, PHP_STREAM_AS_FD_FOR_SELECT, (void *) &id, 1))) {
1119 zval_add_ref(fd);
1120 add_index_zval(&zmap, id, *fd);
1121 FD_SET(id, R);
1122 if (id > nfds) {
1123 nfds = id;
1124 }
1125 }
1126 } else if (Z_TYPE_PP(fd) == IS_LONG) {
1127 FD_SET(Z_LVAL_PP(fd), R);
1128 if (Z_LVAL_PP(fd) > nfds) {
1129 nfds = Z_LVAL_PP(fd);
1130 }
1131 }
1132 }
1133 }
1134
1135 if (w && zend_hash_num_elements(Z_ARRVAL_P(w))) {
1136 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(w));
1137 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(w), (void *) &fd);
1138 zend_hash_move_forward(Z_ARRVAL_P(w))) {
1139 if (Z_TYPE_PP(fd) == IS_RESOURCE) {
1140 php_stream *s = NULL;
1141 int id = 0;
1142
1143 ZEND_FETCH_RESOURCE_NO_RETURN(s, php_stream *, fd, -1, NULL, php_file_le_stream());
1144 if (s && (SUCCESS == php_stream_cast(s, PHP_STREAM_AS_FD_FOR_SELECT, (void *) &id, 1))) {
1145 zval_add_ref(fd);
1146 add_index_zval(&zmap, id, *fd);
1147 FD_SET(id, W);
1148 if (id > nfds) {
1149 nfds = id;
1150 }
1151 }
1152 } else if (Z_TYPE_PP(fd) == IS_LONG) {
1153 FD_SET(Z_LVAL_PP(fd), W);
1154 if (Z_LVAL_PP(fd) > nfds) {
1155 nfds = Z_LVAL_PP(fd);
1156 }
1157 }
1158 }
1159 }
1160
1161 return nfds ? nfds + 1 : 0;
1162 }
1163 /* }}} */
1164
1165 static void php_ares_query_llist_dtor(void *entry)
1166 {
1167 php_ares_query *q = *(php_ares_query **) entry;
1168 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
1169 zend_list_delete(q->id);
1170 }
1171
1172 #ifdef HAVE_ARES_VERSION
1173 /* {{{ proto string ares_version()
1174 Get libares version */
1175 static PHP_FUNCTION(ares_version)
1176 {
1177 if (ZEND_NUM_ARGS()) {
1178 WRONG_PARAM_COUNT;
1179 }
1180
1181 RETURN_STRING(estrdup(ares_version(NULL)), 0);
1182 }
1183 /* }}} */
1184 #endif
1185
1186 /* {{{ proto resource ares_init([array options])
1187 Create an ares resource */
1188 static PHP_FUNCTION(ares_init)
1189 {
1190 zval *opt_array = NULL;
1191 php_ares *ares = NULL;
1192 int err;
1193
1194 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opt_array)) {
1195 RETURN_FALSE;
1196 }
1197
1198 ares = ecalloc(1, sizeof(php_ares));
1199 TSRMLS_SET_CTX(ares->tsrm_ls);
1200 zend_llist_init(&ares->queries, sizeof(php_ares_query *), (llist_dtor_func_t) php_ares_query_llist_dtor, 0);
1201 php_ares_options_ctor(&ares->options, opt_array ? Z_ARRVAL_P(opt_array) : NULL);
1202
1203 if (ARES_SUCCESS != (err = ares_init_options(&ares->channel, &ares->options.strct, ares->options.flags))) {
1204 php_ares_options_dtor(&ares->options);
1205 zend_llist_destroy(&ares->queries);
1206 efree(ares);
1207 RETURN_ARES_ERROR(err);
1208 }
1209
1210 ZEND_REGISTER_RESOURCE(return_value, ares, le_ares);
1211 }
1212 /* }}} */
1213
1214 #ifdef HAVE_ARES_SET_LOCAL_DEV
1215 /* {{{ proto void ares_set_local_dev(resource ares, string dev)
1216 Set the local interface name to bind to. */
1217 static PHP_FUNCTION(ares_set_local_dev)
1218 {
1219 zval *rsrc;
1220 char *dev_str = NULL;
1221 int dev_len = 0;
1222 php_ares *ares;
1223
1224 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!", &rsrc, &dev_str, &dev_len)) {
1225 RETURN_FALSE;
1226 }
1227 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1228
1229 ares_set_local_dev(ares->channel, dev_str);
1230 }
1231 #endif
1232
1233 #ifdef HAVE_ARES_SET_LOCAL_IP4
1234 /* {{{ proto void ares_set_local_ip4(resource ares, int addr)
1235 Set the local IPv4 address to bind to. */
1236 static PHP_FUNCTION(ares_set_local_ip4)
1237 {
1238 zval *rsrc;
1239 long ip4_num;
1240 php_ares *ares;
1241
1242 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &rsrc, &ip4_num)) {
1243 RETURN_FALSE;
1244 }
1245 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1246
1247 ares_set_local_ip4(ares->channel, (unsigned int) ip4_num);
1248 }
1249 #endif
1250
1251 #ifdef HAVE_ARES_SET_LOCAL_IP6
1252 /* {{{ proto void ares_set_local_ip6(resource ares, string addr128bit)
1253 Set the local IPv6 address to bind to. */
1254 static PHP_FUNCTION(ares_set_local_ip6)
1255 {
1256 zval *rsrc;
1257 char *ip6_str;
1258 int ip6_len;
1259 php_ares *ares;
1260
1261 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &rsrc, &ip6_str, &ip6_len)) {
1262 RETURN_FALSE;
1263 }
1264 if (16 != ip6_len) {
1265 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Binary IPv6 address string must be exactly 16 bytes long");
1266 }
1267 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1268
1269 ares_set_local_ip6(ares->channel, (unsigned char *) ip6_str);
1270 }
1271 #endif
1272
1273 /* {{{ proto void ares_destroy(resource ares)
1274 Destroy the ares handle */
1275 static PHP_FUNCTION(ares_destroy)
1276 {
1277 zval *rsrc;
1278 php_ares *ares;
1279
1280 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1281 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1282 if (ares->in_callback) {
1283 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy ares handle while in callback");
1284 } else {
1285 zend_list_delete(Z_LVAL_P(rsrc));
1286 }
1287 }
1288 }
1289 /* }}} */
1290
1291 /* {{{ proto string ares_strerror(int status)
1292 Get description of status code */
1293 static PHP_FUNCTION(ares_strerror)
1294 {
1295 long err;
1296 #ifdef HAVE_OLD_ARES_STRERROR
1297 char *__tmp = NULL;
1298 const char *__err;
1299 #endif
1300
1301 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &err)) {
1302 RETURN_FALSE;
1303 }
1304
1305 #ifdef HAVE_OLD_ARES_STRERROR
1306 __err = ares_strerror(err, &__tmp);
1307 RETVAL_STRING(estrdup(__err), 0);
1308 if (__tmp) {
1309 ares_free_errmem(__tmp);
1310 }
1311 #else
1312 RETURN_STRING(estrdup(ares_strerror(err)), 0);
1313 #endif
1314 }
1315 /* }}} */
1316
1317 /* {{{ proto string ares_mkquery(string name, int dnsclass, int type, int id, int rd)
1318 Compose a custom query */
1319 static PHP_FUNCTION(ares_mkquery)
1320 {
1321 char *name_str, *query_str;
1322 int name_len, query_len, err;
1323 long dnsclass, type, id, rd;
1324
1325 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &name_str, &name_len, &dnsclass, &type, &id, &rd)) {
1326 RETURN_FALSE;
1327 }
1328
1329 if (ARES_SUCCESS != (err = ares_mkquery(name_str, dnsclass, type, id, rd, (unsigned char **) &query_str, &query_len))) {
1330 RETURN_ARES_ERROR(err);
1331 }
1332 RETVAL_STRINGL(query_str, query_len, 1);
1333 ares_free_string(query_str);
1334 }
1335 /* }}} */
1336
1337 /* {{{ proto resource ares_search(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
1338 Issue a domain search for name */
1339 static PHP_FUNCTION(ares_search)
1340 {
1341 zval *rsrc, *cb = NULL;
1342 php_ares *ares;
1343 php_ares_query *query;
1344 char *name;
1345 int name_len;
1346 long dnsclass = C_IN, type = T_A;
1347
1348 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
1349 RETURN_FALSE;
1350 }
1351 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1352
1353 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1354 RETURN_ARES_CB_ERROR("second");
1355 }
1356
1357 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1358 php_ares_query_rsrc(query, return_value);
1359 php_ares_query_pckt(query, PHP_ARES_PCKT_SEARCH, name, name_len, type, dnsclass);
1360 ares_search(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
1361 }
1362 /* }}} */
1363
1364 /* {{{ proto resource ares_query(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
1365 Issue a single DNS query */
1366 static PHP_FUNCTION(ares_query)
1367 {
1368 zval *rsrc, *cb = NULL;
1369 php_ares *ares;
1370 php_ares_query *query;
1371 char *name;
1372 int name_len;
1373 long dnsclass = C_IN, type = T_A;
1374
1375 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
1376 RETURN_FALSE;
1377 }
1378 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1379
1380 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1381 RETURN_ARES_CB_ERROR("second");
1382 }
1383
1384 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1385 php_ares_query_rsrc(query, return_value);
1386 php_ares_query_pckt(query, PHP_ARES_PCKT_QUERY, name, name_len, type, dnsclass);
1387 ares_query(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
1388 }
1389 /* }}} */
1390
1391 /* {{{ proto resource ares_send(resource ares, mixed callback, string buf)
1392 Send custom query */
1393 static PHP_FUNCTION(ares_send)
1394 {
1395 zval *rsrc, *cb = NULL;
1396 php_ares *ares;
1397 php_ares_query *query;
1398 char *buf;
1399 int len;
1400
1401 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s", &rsrc, &cb, &buf, &len)) {
1402 RETURN_FALSE;
1403 }
1404 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1405
1406 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1407 RETURN_ARES_CB_ERROR("second");
1408 }
1409
1410 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1411 php_ares_query_rsrc(query, return_value);
1412 php_ares_query_pckt(query, PHP_ARES_PCKT_SEND, buf, len);
1413 ares_send(ares->channel, (const unsigned char *) buf, len, php_ares_callback_func, query);
1414 }
1415 /* }}} */
1416
1417 /* {{{ proto resource ares_gethostbyname(resource ares, mixed callback, string name[, int family = AF_INET])
1418 Get host by name */
1419 static PHP_FUNCTION(ares_gethostbyname)
1420 {
1421 zval *rsrc, *cb = NULL;
1422 php_ares *ares;
1423 php_ares_query *query;
1424 char *name;
1425 int name_len;
1426 long family = AF_INET;
1427
1428 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &name, &name_len, &family)) {
1429 RETURN_FALSE;
1430 }
1431 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1432
1433 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1434 RETURN_ARES_CB_ERROR("second");
1435 }
1436
1437 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
1438 php_ares_query_rsrc(query, return_value);
1439 php_ares_query_pckt(query, PHP_ARES_PCKT_HNAME, name, name_len, family);
1440 ares_gethostbyname(ares->channel, name, family, php_ares_host_callback_func, query);
1441 }
1442 /* }}} */
1443
1444 /* {{{ proto resource ares_gethostbyaddr(resuorce ares, mixed callback, string address[, int family = ARES_AF_INET])
1445 Get host by address */
1446 static PHP_FUNCTION(ares_gethostbyaddr)
1447 {
1448 zval *rsrc, *cb = NULL;
1449 php_ares *ares;
1450 php_ares_query *query;
1451 char *addr;
1452 int addr_len;
1453 long family = AF_INET;
1454 void *sa;
1455 int sa_len;
1456
1457 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &addr, &addr_len, &family)) {
1458 RETURN_FALSE;
1459 }
1460 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1461
1462 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1463 PHP_ARES_CB_ERROR("second");
1464 RETURN_FALSE;
1465 }
1466
1467 switch (family) {
1468 case AF_INET:
1469 sa = emalloc(sa_len = sizeof(struct in_addr));
1470 break;
1471 case AF_INET6:
1472 sa = emalloc(sa_len = sizeof(struct in6_addr));
1473 break;
1474 default:
1475 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither ARES_AF_INET nor ARES_AF_INET6");
1476 RETURN_FALSE;
1477 break;
1478 }
1479
1480 if (1 > inet_pton(family, addr, sa)) {
1481 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1482 RETVAL_FALSE;
1483 } else {
1484 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
1485 php_ares_query_rsrc(query, return_value);
1486 php_ares_query_pckt(query, PHP_ARES_PCKT_HADDR, addr, addr_len, family);
1487 ares_gethostbyaddr(ares->channel, sa, sa_len, family, php_ares_host_callback_func, query);
1488 }
1489 efree(sa);
1490 }
1491 /* }}} */
1492
1493 #ifdef HAVE_ARES_GETNAMEINFO
1494 /* {{{ proto resource ares_getnameinfo(resource ares, mixed callback, int flags, string addr[, int family = ARES_AF_INET[, int port = 0]])
1495 Get name info */
1496 static PHP_FUNCTION(ares_getnameinfo)
1497 {
1498 zval *rsrc, *cb = NULL;
1499 php_ares *ares;
1500 php_ares_query *query;
1501 char *addr;
1502 int addr_len;
1503 long flags, port = 0, family = AF_INET;
1504 struct sockaddr *sa;
1505 struct sockaddr_in *in;
1506 struct sockaddr_in6 *in6;
1507 int sa_len;
1508
1509 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!ls|ll", &rsrc, &cb, &flags, &addr, &addr_len, &family, &port)) {
1510 RETURN_FALSE;
1511 }
1512 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1513
1514 if (cb && !PHP_ARES_IS_CALLABLE(cb, 0, NULL)) {
1515 PHP_ARES_CB_ERROR("second");
1516 RETURN_FALSE;
1517 }
1518
1519 RETVAL_TRUE;
1520 switch (family) {
1521 case AF_INET:
1522 in = ecalloc(1, sa_len = sizeof(struct sockaddr_in));
1523 in->sin_family = AF_INET;
1524 in->sin_port = htons((unsigned short) port);
1525 if (1 > inet_pton(in->sin_family, addr, &in->sin_addr)) {
1526 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1527 RETVAL_FALSE;
1528 }
1529 sa = (struct sockaddr *) in;
1530 break;
1531 case AF_INET6:
1532 in6 = ecalloc(1, sa_len = sizeof(struct sockaddr_in6));
1533 in6->sin6_family = AF_INET6;
1534 in6->sin6_port = htons((unsigned short) port);
1535 if (1 > inet_pton(in6->sin6_family, addr, &in6->sin6_addr)) {
1536 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1537 RETVAL_FALSE;
1538 }
1539 sa = (struct sockaddr *) in6;
1540 break;
1541 default:
1542 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither AF_INET nor AF_INET6");
1543 RETURN_FALSE;
1544 break;
1545 }
1546
1547 if (Z_BVAL_P(return_value)) {
1548 query = php_ares_query_ctor(NULL, PHP_ARES_CB_NINFO, ares, cb);
1549 php_ares_query_rsrc(query, return_value);
1550 php_ares_query_pckt(query, PHP_ARES_PCKT_NINFO, flags, addr, addr_len, family, port);
1551 ares_getnameinfo(ares->channel, sa, sa_len, flags, php_ares_nameinfo_callback_func, query);
1552 }
1553 efree(sa);
1554 }
1555 /* }}} */
1556 #endif
1557
1558 /* {{{ proto mixed ares_result(resource query, int &errno, string &error)
1559 Check a query for its result */
1560 static PHP_FUNCTION(ares_result)
1561 {
1562 zval *rsrc, *zerrno = NULL, *zerror = NULL;
1563 php_ares_query *query;
1564
1565 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &rsrc, &zerrno, &zerror)) {
1566 RETURN_FALSE;
1567 }
1568 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1569
1570 if (zerrno) {
1571 zval_dtor(zerrno);
1572 ZVAL_LONG(zerrno, query->error);
1573 }
1574 if (zerror) {
1575 zval_dtor(zerror);
1576 ZVAL_NULL(zerror);
1577 }
1578
1579 switch (query->error) {
1580 case -1:
1581 RETVAL_FALSE;
1582 break;
1583 default:
1584 if (zerror) {
1585 #ifdef HAVE_OLD_ARES_STRERROR
1586 char *__tmp = NULL;
1587 const char *__err = ares_strerror(query->error, &__tmp);
1588 ZVAL_STRING(zerror, estrdup(__err), 0);
1589 if (__tmp) ares_free_errmem(__tmp);
1590 #else
1591 ZVAL_STRING(zerror, estrdup(ares_strerror(query->error)), 0);
1592 #endif
1593 }
1594 RETVAL_FALSE;
1595 /* no break */
1596 case 0:
1597 switch (query->type) {
1598 case PHP_ARES_CB_STD:
1599 if (query->result.std.arr) {
1600 RETVAL_ZVAL(query->result.std.arr, 1, 0);
1601 } else if (query->result.std.len > 0) {
1602 RETVAL_STRINGL(query->result.std.buf, query->result.std.len, 1);
1603 }
1604 break;
1605 case PHP_ARES_CB_HOST:
1606 if (query->result.host.h_name) {
1607 object_init(return_value);
1608 php_ares_hostent_to_struct(&query->result.host, HASH_OF(return_value));
1609 }
1610 break;
1611 case PHP_ARES_CB_NINFO:
1612 if (query->result.ninfo.node || query->result.ninfo.service) {
1613 object_init(return_value);
1614 add_property_string(return_value, "node", query->result.ninfo.node ? query->result.ninfo.node : "", 1);
1615 add_property_string(return_value, "service", query->result.ninfo.service ? query->result.ninfo.service : "", 1);
1616 }
1617 break;
1618 }
1619 break;
1620 }
1621 }
1622 /* }}} */
1623
1624 /* {{{ proto object ares_packet(resource query)
1625 Check a query for its question packet */
1626 static PHP_FUNCTION(ares_packet)
1627 {
1628 zval *rsrc, *prop;
1629 php_ares_query *query;
1630
1631 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1632 RETURN_FALSE;
1633 }
1634 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1635
1636 object_init(return_value);
1637 add_property_long(return_value, "type", query->packet.type);
1638 add_property_null(return_value, "search");
1639 add_property_null(return_value, "query");
1640 add_property_null(return_value, "send");
1641 add_property_null(return_value, "gethostbyname");
1642 add_property_null(return_value, "gethostbyaddr");
1643 add_property_null(return_value, "getnameinfo");
1644 MAKE_STD_ZVAL(prop);
1645
1646 switch (query->packet.type) {
1647 case PHP_ARES_PCKT_SEARCH:
1648 object_init(prop);
1649 add_property_stringl(prop, "name", query->packet.data.search.name, query->packet.data.search.name_len, 1);
1650 add_property_long(prop, "type", query->packet.data.search.type);
1651 add_property_long(prop, "dnsclass", query->packet.data.search.dnsclass);
1652 add_property_zval(return_value, "search", prop);
1653 break;
1654
1655 case PHP_ARES_PCKT_QUERY:
1656 object_init(prop);
1657 add_property_stringl(prop, "name", query->packet.data.query.name, query->packet.data.query.name_len, 1);
1658 add_property_long(prop, "type", query->packet.data.query.type);
1659 add_property_long(prop, "dnsclass", query->packet.data.query.dnsclass);
1660 add_property_zval(return_value, "query", prop);
1661 break;
1662
1663 case PHP_ARES_PCKT_SEND:
1664 ZVAL_STRINGL(prop, query->packet.data.send.buf, query->packet.data.send.len, 1);
1665 add_property_zval(return_value, "send", prop);
1666 break;
1667
1668 case PHP_ARES_PCKT_HNAME:
1669 object_init(prop);
1670 add_property_stringl(prop, "name", query->packet.data.hname.name, query->packet.data.hname.name_len, 1);
1671 add_property_long(prop, "family", query->packet.data.hname.family);
1672 add_property_zval(return_value, "gethostbyname", prop);
1673 break;
1674
1675 case PHP_ARES_PCKT_HADDR:
1676 object_init(prop);
1677 add_property_stringl(prop, "addr", query->packet.data.haddr.addr, query->packet.data.haddr.addr_len, 1);
1678 add_property_long(prop, "family", query->packet.data.haddr.family);
1679 add_property_zval(return_value, "gethostbyaddr", prop);
1680 break;
1681
1682 case PHP_ARES_PCKT_NINFO:
1683 object_init(prop);
1684 add_property_long(prop, "flags", query->packet.data.ninfo.flags);
1685 add_property_stringl(prop, "addr", query->packet.data.ninfo.addr, query->packet.data.ninfo.addr_len, 1);
1686 add_property_long(prop, "family", query->packet.data.ninfo.family);
1687 add_property_long(prop, "port", query->packet.data.ninfo.port);
1688 add_property_zval(return_value, "getnameinfo", prop);
1689 break;
1690 }
1691
1692 zval_ptr_dtor(&prop);
1693 }
1694 /* }}} */
1695
1696 #ifdef HAVE_ARES_CANCEL
1697 /* {{{ proto void ares_cancel(resource ares)
1698 Cancel pending queries */
1699 static PHP_FUNCTION(ares_cancel)
1700 {
1701 zval *rsrc;
1702 php_ares *ares;
1703
1704 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1705 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1706 ares_cancel(ares->channel);
1707 }
1708 }
1709 /* }}} */
1710 #endif
1711
1712 /* {{{ proto void ares_process_all(resource ares[, int max_timeout_ms])
1713 Process all pending queries */
1714 static PHP_FUNCTION(ares_process_all)
1715 {
1716 zval *rsrc;
1717 php_ares *ares;
1718 long max_timeout = -1;
1719
1720 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1721 RETURN_FALSE;
1722 }
1723 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1724
1725 while (php_ares_process(ares, max_timeout));
1726 }
1727 /* }}} */
1728
1729 /* {{{ proto bool ares_process_once(resource ares[, int max_timout_ms])
1730 Process once and return whether it should be called again */
1731 static PHP_FUNCTION(ares_process_once)
1732 {
1733 zval *rsrc;
1734 php_ares *ares;
1735 long max_timeout = -1;
1736
1737 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1738 RETURN_FALSE;
1739 }
1740 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1741
1742 RETVAL_BOOL(php_ares_process(ares, max_timeout));
1743 }
1744 /* }}} */
1745
1746 /* {{{ proto void ares_process(resource ares, array read, array write)
1747 Process call */
1748 static PHP_FUNCTION(ares_process)
1749 {
1750 zval *rsrc, *read = NULL, *write = NULL;
1751 fd_set R, W;
1752 php_ares *ares;
1753
1754 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a!a!", &rsrc, &read, &write)) {
1755 RETURN_FALSE;
1756 }
1757 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1758
1759 FD_ZERO(&R);
1760 FD_ZERO(&W);
1761
1762 php_ares_extract_fds(read, write, &R, &W, NULL TSRMLS_CC);
1763 ares_process(ares->channel, &R, &W);
1764 }
1765 /* }}} */
1766
1767 /* proto bool ares_select(array &read, array &write, int timeout_ms)
1768 Select call */
1769 static PHP_FUNCTION(ares_select)
1770 {
1771 zval *read = NULL, *write = NULL;
1772 fd_set R, W;
1773 int nfds;
1774 long timeout;
1775 struct timeval tv;
1776 HashTable resource_map;
1777
1778 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aal", &read, &write, &timeout)) {
1779 RETURN_FALSE;
1780 }
1781
1782 if (timeout) {
1783 tv.tv_sec = timeout / 1000;
1784 tv.tv_usec = timeout % (timeout * 1000);
1785 } else {
1786 tv.tv_sec = 1;
1787 tv.tv_usec = 0;
1788 }
1789
1790 FD_ZERO(&R);
1791 FD_ZERO(&W);
1792
1793 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);
1794 nfds = php_ares_extract_fds(read, write, &R, &W, &resource_map TSRMLS_CC);
1795 if (-1 < select(nfds, &R, &W, NULL, &tv)) {
1796 zend_hash_clean(Z_ARRVAL_P(read));
1797 zend_hash_clean(Z_ARRVAL_P(write));
1798 php_ares_publish_fds(&R, &W, read, write, &resource_map);
1799 RETVAL_TRUE;
1800 } else {
1801 RETVAL_FALSE;
1802 }
1803 zend_hash_destroy(&resource_map);
1804 }
1805 /* }}} */
1806
1807 /* proto int ares_timeout(resource ares[, int max_timout_ms])
1808 Get suggested select timeout in ms */
1809 static PHP_FUNCTION(ares_timeout)
1810 {
1811 zval *rsrc;
1812 long max_timeout = -1;
1813 struct timeval tv, *tvptr;
1814 php_ares *ares;
1815
1816 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1817 RETURN_FALSE;
1818 }
1819 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1820
1821 if ((tvptr = php_ares_timeout(ares, max_timeout, &tv))) {
1822 RETURN_LONG(tvptr->tv_sec * 1000 + tvptr->tv_usec / 1000);
1823 }
1824 RETURN_LONG(0);
1825 }
1826 /* }}} */
1827
1828 /* {{{ proto int ares_fds(resource ares, array &read, array &write)
1829 Get file descriptors */
1830 static PHP_FUNCTION(ares_fds)
1831 {
1832 zval *rsrc, *read, *write;
1833 fd_set R, W;
1834 php_ares *ares;
1835
1836 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz", &rsrc, &read, &write)) {
1837 RETURN_FALSE;
1838 }
1839 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1840
1841 FD_ZERO(&R);
1842 FD_ZERO(&W);
1843
1844 zval_dtor(read);
1845 zval_dtor(write);
1846 array_init(read);
1847 array_init(write);
1848 ares_fds(ares->channel, &R, &W);
1849 RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write, NULL));
1850 }
1851 /* }}} */
1852
1853 static ZEND_RSRC_DTOR_FUNC(php_ares_le_dtor)
1854 {
1855 php_ares *ares = (php_ares *) rsrc->ptr;
1856
1857 ares_destroy(ares->channel);
1858 zend_llist_destroy(&ares->queries);
1859 php_ares_options_dtor(&ares->options);
1860 efree(ares);
1861 }
1862
1863 static ZEND_RSRC_DTOR_FUNC(php_ares_query_le_dtor)
1864 {
1865 php_ares_query *query = (php_ares_query *) rsrc->ptr;
1866
1867 php_ares_query_dtor(query);
1868 efree(query);
1869 }
1870
1871 /* {{{ PHP_MINIT_FUNCTION */
1872 static PHP_MINIT_FUNCTION(ares)
1873 {
1874 #ifdef HAVE_ARES_LIBRARY_INIT
1875 if (ARES_SUCCESS != ares_library_init(ARES_LIB_INIT_ALL)) {
1876 return FAILURE;
1877 }
1878 #endif
1879 #ifdef HAVE_ARES_VERSION
1880 {
1881 int ares_version_num;
1882 ares_version(&ares_version_num);
1883
1884 REGISTER_LONG_CONSTANT("ARES_VERSION", ares_version_num, CONST_PERSISTENT|CONST_CS);
1885 }
1886 #endif
1887
1888 REGISTER_LONG_CONSTANT("ARES_SUCCESS", ARES_SUCCESS, CONST_PERSISTENT|CONST_CS);
1889 REGISTER_LONG_CONSTANT("ARES_ENODATA", ARES_ENODATA, CONST_PERSISTENT|CONST_CS);
1890 REGISTER_LONG_CONSTANT("ARES_EFORMERR", ARES_EFORMERR, CONST_PERSISTENT|CONST_CS);
1891 REGISTER_LONG_CONSTANT("ARES_ESERVFAIL", ARES_ESERVFAIL, CONST_PERSISTENT|CONST_CS);
1892 REGISTER_LONG_CONSTANT("ARES_ENOTFOUND", ARES_ENOTFOUND, CONST_PERSISTENT|CONST_CS);
1893 REGISTER_LONG_CONSTANT("ARES_ENOTIMP", ARES_ENOTIMP, CONST_PERSISTENT|CONST_CS);
1894 REGISTER_LONG_CONSTANT("ARES_EREFUSED", ARES_EREFUSED, CONST_PERSISTENT|CONST_CS);
1895 REGISTER_LONG_CONSTANT("ARES_EBADQUERY", ARES_EBADQUERY, CONST_PERSISTENT|CONST_CS);
1896 REGISTER_LONG_CONSTANT("ARES_EBADNAME", ARES_EBADNAME, CONST_PERSISTENT|CONST_CS);
1897 REGISTER_LONG_CONSTANT("ARES_EBADFAMILY", ARES_EBADFAMILY, CONST_PERSISTENT|CONST_CS);
1898 REGISTER_LONG_CONSTANT("ARES_EBADRESP", ARES_EBADRESP, CONST_PERSISTENT|CONST_CS);
1899 REGISTER_LONG_CONSTANT("ARES_ECONNREFUSED", ARES_ECONNREFUSED, CONST_PERSISTENT|CONST_CS);
1900 REGISTER_LONG_CONSTANT("ARES_ETIMEOUT", ARES_ETIMEOUT, CONST_PERSISTENT|CONST_CS);
1901 REGISTER_LONG_CONSTANT("ARES_EOF", ARES_EOF, CONST_PERSISTENT|CONST_CS);
1902 REGISTER_LONG_CONSTANT("ARES_EFILE", ARES_EFILE, CONST_PERSISTENT|CONST_CS);
1903 REGISTER_LONG_CONSTANT("ARES_ENOMEM", ARES_ENOMEM, CONST_PERSISTENT|CONST_CS);
1904 REGISTER_LONG_CONSTANT("ARES_EDESTRUCTION", ARES_EDESTRUCTION, CONST_PERSISTENT|CONST_CS);
1905 #ifdef ARES_EBADSTR
1906 REGISTER_LONG_CONSTANT("ARES_EBADSTR", ARES_EBADSTR, CONST_PERSISTENT|CONST_CS);
1907 #endif
1908 #ifdef ARES_EBADFLAGS
1909 REGISTER_LONG_CONSTANT("ARES_EBADFLAGS", ARES_EBADFLAGS, CONST_PERSISTENT|CONST_CS);
1910 #endif
1911 #ifdef ARES_ENONAME
1912 REGISTER_LONG_CONSTANT("ARES_ENONAME", ARES_ENONAME, CONST_PERSISTENT|CONST_CS);
1913 #endif
1914 #ifdef ARES_EBADHINTS
1915 REGISTER_LONG_CONSTANT("ARES_EBADHINTS", ARES_EBADHINTS, CONST_PERSISTENT|CONST_CS);
1916 #endif
1917 #ifdef ARES_ENOTINITIALIZED
1918 REGISTER_LONG_CONSTANT("ARES_ENOTINITIALIZED", ARES_ENOTINITIALIZED, CONST_PERSISTENT|CONST_CS);
1919 #endif
1920 #ifdef ARES_ELOADIPHLPAPI
1921 REGISTER_LONG_CONSTANT("ARES_ELOADIPHLPAPI", ARES_ELOADIPHLPAPI, CONST_PERSISTENT|CONST_CS);
1922 #endif
1923 #ifdef ARES_EADDRGETNETWORKPARAMS
1924 REGISTER_LONG_CONSTANT("ARES_EADDRGETNETWORKPARAMS", ARES_EADDRGETNETWORKPARAMS, CONST_PERSISTENT|CONST_CS);
1925 #endif
1926 #ifdef ARES_ECANCELLED
1927 REGISTER_LONG_CONSTANT("ARES_ECANCELLED", ARES_ECANCELLED, CONST_PERSISTENT|CONST_CS);
1928 #endif
1929
1930 REGISTER_LONG_CONSTANT("ARES_FLAG_USEVC", ARES_FLAG_USEVC, CONST_PERSISTENT|CONST_CS);
1931 REGISTER_LONG_CONSTANT("ARES_FLAG_PRIMARY", ARES_FLAG_PRIMARY, CONST_PERSISTENT|CONST_CS);
1932 REGISTER_LONG_CONSTANT("ARES_FLAG_IGNTC", ARES_FLAG_IGNTC, CONST_PERSISTENT|CONST_CS);
1933 REGISTER_LONG_CONSTANT("ARES_FLAG_NORECURSE", ARES_FLAG_NORECURSE, CONST_PERSISTENT|CONST_CS);
1934 REGISTER_LONG_CONSTANT("ARES_FLAG_STAYOPEN", ARES_FLAG_STAYOPEN, CONST_PERSISTENT|CONST_CS);
1935 REGISTER_LONG_CONSTANT("ARES_FLAG_NOSEARCH", ARES_FLAG_NOSEARCH, CONST_PERSISTENT|CONST_CS);
1936 REGISTER_LONG_CONSTANT("ARES_FLAG_NOALIASES", ARES_FLAG_NOALIASES, CONST_PERSISTENT|CONST_CS);
1937 REGISTER_LONG_CONSTANT("ARES_FLAG_NOCHECKRESP", ARES_FLAG_NOCHECKRESP, CONST_PERSISTENT|CONST_CS);
1938 #ifdef ARES_FLAG_EDNS
1939 REGISTER_LONG_CONSTANT("ARES_FLAG_EDNS", ARES_FLAG_EDNS, CONST_PERSISTENT|CONST_CS);
1940 #endif
1941
1942 /*
1943 * Address Family Constants
1944 */
1945 REGISTER_LONG_CONSTANT("ARES_AF_INET", AF_INET, CONST_PERSISTENT|CONST_CS);
1946 REGISTER_LONG_CONSTANT("ARES_AF_INET6", AF_INET6, CONST_PERSISTENT|CONST_CS);
1947
1948 /*
1949 * Name Info constants
1950 */
1951 #ifdef ARES_NI_NOFQDN
1952 REGISTER_LONG_CONSTANT("ARES_NI_NOFQDN", ARES_NI_NOFQDN, CONST_PERSISTENT|CONST_CS);
1953 #endif
1954 #ifdef ARES_NI_NUMERICHOST
1955 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICHOST", ARES_NI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
1956 #endif
1957 #ifdef ARES_NI_NAMEREQD
1958 REGISTER_LONG_CONSTANT("ARES_NI_NAMEREQD", ARES_NI_NAMEREQD, CONST_PERSISTENT|CONST_CS);
1959 #endif
1960 #ifdef ARES_NI_NUMERICSERV
1961 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSERV", ARES_NI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
1962 #endif
1963 #ifdef ARES_NI_DGRAM
1964 REGISTER_LONG_CONSTANT("ARES_NI_DGRAM", ARES_NI_DGRAM, CONST_PERSISTENT|CONST_CS);
1965 #endif
1966 #ifdef ARES_NI_TCP
1967 REGISTER_LONG_CONSTANT("ARES_NI_TCP", ARES_NI_TCP, CONST_PERSISTENT|CONST_CS);
1968 #endif
1969 #ifdef ARES_NI_UDP
1970 REGISTER_LONG_CONSTANT("ARES_NI_UDP", ARES_NI_UDP, CONST_PERSISTENT|CONST_CS);
1971 #endif
1972 #ifdef ARES_NI_SCTP
1973 REGISTER_LONG_CONSTANT("ARES_NI_SCTP", ARES_NI_SCTP, CONST_PERSISTENT|CONST_CS);
1974 #endif
1975 #ifdef ARES_NI_DCCP
1976 REGISTER_LONG_CONSTANT("ARES_NI_DCCP", ARES_NI_DCCP, CONST_PERSISTENT|CONST_CS);
1977 #endif
1978 #ifdef ARES_NI_NUMERICSCOPE
1979 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSCOPE", ARES_NI_NUMERICSCOPE, CONST_PERSISTENT|CONST_CS);
1980 #endif
1981 #ifdef ARES_NI_LOOKUPHOST
1982 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPHOST", ARES_NI_LOOKUPHOST, CONST_PERSISTENT|CONST_CS);
1983 #endif
1984 #ifdef ARES_NI_LOOKUPSERVICE
1985 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPSERVICE", ARES_NI_LOOKUPSERVICE, CONST_PERSISTENT|CONST_CS);
1986 #endif
1987 #ifdef ARES_NI_IDN
1988 REGISTER_LONG_CONSTANT("ARES_NI_IDN", ARES_NI_IDN, CONST_PERSISTENT|CONST_CS);
1989 #endif
1990 #ifdef ARES_NI_IDN_ALLOW_UNASSIGNED
1991 REGISTER_LONG_CONSTANT("ARES_NI_IDN_ALLOW_UNASSIGNED", ARES_NI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
1992 #endif
1993 #ifdef ARES_NI_IDN_USE_STD
1994 REGISTER_LONG_CONSTANT("ARES_NI_IDN_USE_STD", ARES_NI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
1995 #endif
1996
1997 /*
1998 * Address Info constants
1999 */
2000 #ifdef ARES_AI_CANONNAME
2001 REGISTER_LONG_CONSTANT("ARES_AI_CANONNAME", ARES_AI_CANONNAME, CONST_PERSISTENT|CONST_CS);
2002 #endif
2003 #ifdef ARES_AI_NUMERICHOST
2004 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICHOST", ARES_AI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
2005 #endif
2006 #ifdef ARES_AI_PASSIVE
2007 REGISTER_LONG_CONSTANT("ARES_AI_PASSIVE", ARES_AI_PASSIVE, CONST_PERSISTENT|CONST_CS);
2008 #endif
2009 #ifdef ARES_AI_NUMERICSERV
2010 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICSERV", ARES_AI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
2011 #endif
2012 #ifdef ARES_AI_V
2013 REGISTER_LONG_CONSTANT("ARES_AI_V", ARES_AI_V, CONST_PERSISTENT|CONST_CS);
2014 #endif
2015 #ifdef ARES_AI_ALL
2016 REGISTER_LONG_CONSTANT("ARES_AI_ALL", ARES_AI_ALL, CONST_PERSISTENT|CONST_CS);
2017 #endif
2018 #ifdef ARES_AI_ADDRCONFIG
2019 REGISTER_LONG_CONSTANT("ARES_AI_ADDRCONFIG", ARES_AI_ADDRCONFIG, CONST_PERSISTENT|CONST_CS);
2020 #endif
2021 #ifdef ARES_AI_IDN
2022 REGISTER_LONG_CONSTANT("ARES_AI_IDN", ARES_AI_IDN, CONST_PERSISTENT|CONST_CS);
2023 #endif
2024 #ifdef ARES_AI_IDN_ALLOW_UNASSIGNED
2025 REGISTER_LONG_CONSTANT("ARES_AI_IDN_ALLOW_UNASSIGNED", ARES_AI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
2026 #endif
2027 #ifdef ARES_AI_IDN_USE_STD
2028 REGISTER_LONG_CONSTANT("ARES_AI_IDN_USE_STD", ARES_AI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
2029 #endif
2030 #ifdef ARES_AI_CANONIDN
2031 REGISTER_LONG_CONSTANT("ARES_AI_CANONIDN", ARES_AI_CANONIDN, CONST_PERSISTENT|CONST_CS);
2032 #endif
2033 #ifdef ARES_AI_MASK
2034 REGISTER_LONG_CONSTANT("ARES_AI_MASK", ARES_AI_MASK, CONST_PERSISTENT|CONST_CS);
2035 #endif
2036 #ifdef ARES_GETSOCK_MAXNUM
2037 REGISTER_LONG_CONSTANT("ARES_GETSOCK_MAXNUM", ARES_GETSOCK_MAXNUM, CONST_PERSISTENT|CONST_CS);
2038 #endif
2039
2040 /*
2041 * ns_t (type) constants (arpa/nameser.h)
2042 */
2043 #ifdef T_A
2044 /* (1) Host address. */
2045 REGISTER_LONG_CONSTANT("ARES_T_A", T_A, CONST_CS|CONST_PERSISTENT);
2046 #endif
2047 #ifdef T_NS
2048 /* (2) Authoritative server. */
2049 REGISTER_LONG_CONSTANT("ARES_T_NS", T_NS, CONST_CS|CONST_PERSISTENT);
2050 #endif
2051 #ifdef T_MD
2052 /* (3) Mail destination. */
2053 REGISTER_LONG_CONSTANT("ARES_T_MD", T_MD, CONST_CS|CONST_PERSISTENT);
2054 #endif
2055 #ifdef T_MF
2056 /* (4) Mail forwarder. */
2057 REGISTER_LONG_CONSTANT("ARES_T_MF", T_MF, CONST_CS|CONST_PERSISTENT);
2058 #endif
2059 #ifdef T_CNAME
2060 /* (5) Canonical name. */
2061 REGISTER_LONG_CONSTANT("ARES_T_CNAME", T_CNAME, CONST_CS|CONST_PERSISTENT);
2062 #endif
2063 #ifdef T_SOA
2064 /* (6) Start of authority zone. */
2065 REGISTER_LONG_CONSTANT("ARES_T_SOA", T_SOA, CONST_CS|CONST_PERSISTENT);
2066 #endif
2067 #ifdef T_MB
2068 /* (7) Mailbox domain name. */
2069 REGISTER_LONG_CONSTANT("ARES_T_MB", T_MB, CONST_CS|CONST_PERSISTENT);
2070 #endif
2071 #ifdef T_MG
2072 /* (8) Mail group member. */
2073 REGISTER_LONG_CONSTANT("ARES_T_MG", T_MG, CONST_CS|CONST_PERSISTENT);
2074 #endif
2075 #ifdef T_MR
2076 /* (9) Mail rename name. */
2077 REGISTER_LONG_CONSTANT("ARES_T_MR", T_MR, CONST_CS|CONST_PERSISTENT);
2078 #endif
2079 #ifdef T_NULL
2080 /* (10) Null resource record. */
2081 REGISTER_LONG_CONSTANT("ARES_T_NULL", T_NULL, CONST_CS|CONST_PERSISTENT);
2082 #endif
2083 #ifdef T_WKS
2084 /* (11) Well known service. */
2085 REGISTER_LONG_CONSTANT("ARES_T_WKS", T_WKS, CONST_CS|CONST_PERSISTENT);
2086 #endif
2087 #ifdef T_PTR
2088 /* (12) Domain name pointer. */
2089 REGISTER_LONG_CONSTANT("ARES_T_PTR", T_PTR, CONST_CS|CONST_PERSISTENT);
2090 #endif
2091 #ifdef T_HINFO
2092 /* (13) Host information. */
2093 REGISTER_LONG_CONSTANT("ARES_T_HINFO", T_HINFO, CONST_CS|CONST_PERSISTENT);
2094 #endif
2095 #ifdef T_MINFO
2096 /* (14) Mailbox information. */
2097 REGISTER_LONG_CONSTANT("ARES_T_MINFO", T_MINFO, CONST_CS|CONST_PERSISTENT);
2098 #endif
2099 #ifdef T_MX
2100 /* (15) Mail routing information. */
2101 REGISTER_LONG_CONSTANT("ARES_T_MX", T_MX, CONST_CS|CONST_PERSISTENT);
2102 #endif
2103 #ifdef T_TXT
2104 /* (16) Text strings. */
2105 REGISTER_LONG_CONSTANT("ARES_T_TXT", T_TXT, CONST_CS|CONST_PERSISTENT);
2106 #endif
2107 #ifdef T_RP
2108 /* (17) Responsible person. */
2109 REGISTER_LONG_CONSTANT("ARES_T_RP", T_RP, CONST_CS|CONST_PERSISTENT);
2110 #endif
2111 #ifdef T_AFSDB
2112 /* (18) AFS cell database. */
2113 REGISTER_LONG_CONSTANT("ARES_T_AFSDB", T_AFSDB, CONST_CS|CONST_PERSISTENT);
2114 #endif
2115 #ifdef T_X25
2116 /* (19) X_25 calling address. */
2117 REGISTER_LONG_CONSTANT("ARES_T_X25", T_X25, CONST_CS|CONST_PERSISTENT);
2118 #endif
2119 #ifdef T_ISDN
2120 /* (20) ISDN calling address. */
2121 REGISTER_LONG_CONSTANT("ARES_T_ISDN", T_ISDN, CONST_CS|CONST_PERSISTENT);
2122 #endif
2123 #ifdef T_RT
2124 /* (21) Router. */
2125 REGISTER_LONG_CONSTANT("ARES_T_RT", T_RT, CONST_CS|CONST_PERSISTENT);
2126 #endif
2127 #ifdef T_NSAP
2128 /* (22) NSAP address. */
2129 REGISTER_LONG_CONSTANT("ARES_T_NSAP", T_NSAP, CONST_CS|CONST_PERSISTENT);
2130 #endif
2131 #ifdef T_NSAP_PTR
2132 /* (23) Reverse NSAP lookup (deprecated). */
2133 REGISTER_LONG_CONSTANT("ARES_T_NSAP_PTR", T_NSAP_PTR, CONST_CS|CONST_PERSISTENT);
2134 #endif
2135 #ifdef T_SIG
2136 /* (24) Security signature. */
2137 REGISTER_LONG_CONSTANT("ARES_T_SIG", T_SIG, CONST_CS|CONST_PERSISTENT);
2138 #endif
2139 #ifdef T_KEY
2140 /* (25) Security key. */
2141 REGISTER_LONG_CONSTANT("ARES_T_KEY", T_KEY, CONST_CS|CONST_PERSISTENT);
2142 #endif
2143 #ifdef T_PX
2144 /* (26) X.400 mail mapping. */
2145 REGISTER_LONG_CONSTANT("ARES_T_PX", T_PX, CONST_CS|CONST_PERSISTENT);
2146 #endif
2147 #ifdef T_GPOS
2148 /* (27) Geographical position (withdrawn). */
2149 REGISTER_LONG_CONSTANT("ARES_T_GPOS", T_GPOS, CONST_CS|CONST_PERSISTENT);
2150 #endif
2151 #ifdef T_AAAA
2152 /* (28) Ip6 Address. */
2153 REGISTER_LONG_CONSTANT("ARES_T_AAAA", T_AAAA, CONST_CS|CONST_PERSISTENT);
2154 #endif
2155 #ifdef T_LOC
2156 /* (29) Location Information. */
2157 REGISTER_LONG_CONSTANT("ARES_T_LOC", T_LOC, CONST_CS|CONST_PERSISTENT);
2158 #endif
2159 #ifdef T_NXT
2160 /* (30) Next domain (security). */
2161 REGISTER_LONG_CONSTANT("ARES_T_NXT", T_NXT, CONST_CS|CONST_PERSISTENT);
2162 #endif
2163 #ifdef T_EID
2164 /* (31) Endpoint identifier. */
2165 REGISTER_LONG_CONSTANT("ARES_T_EID", T_EID, CONST_CS|CONST_PERSISTENT);
2166 #endif
2167 #ifdef T_NIMLOC
2168 /* (32) Nimrod Locator. */
2169 REGISTER_LONG_CONSTANT("ARES_T_NIMLOC", T_NIMLOC, CONST_CS|CONST_PERSISTENT);
2170 #endif
2171 #ifdef T_SRV
2172 /* (33) Server Selection. */
2173 REGISTER_LONG_CONSTANT("ARES_T_SRV", T_SRV, CONST_CS|CONST_PERSISTENT);
2174 #endif
2175 #ifdef T_ATMA
2176 /* (34) ATM Address */
2177 REGISTER_LONG_CONSTANT("ARES_T_ATMA", T_ATMA, CONST_CS|CONST_PERSISTENT);
2178 #endif
2179 #ifdef T_NAPTR
2180 /* (35) Naming Authority Pointer */
2181 REGISTER_LONG_CONSTANT("ARES_T_NAPTR", T_NAPTR, CONST_CS|CONST_PERSISTENT);
2182 #endif
2183 #ifdef T_KX
2184 /* (36) Key Exchange */
2185 REGISTER_LONG_CONSTANT("ARES_T_KX", T_KX, CONST_CS|CONST_PERSISTENT);
2186 #endif
2187 #ifdef T_CERT
2188 /* (37) Certification record */
2189 REGISTER_LONG_CONSTANT("ARES_T_CERT", T_CERT, CONST_CS|CONST_PERSISTENT);
2190 #endif
2191 #ifdef T_A6
2192 /* (38) IPv6 address (deprecates AAAA) */
2193 REGISTER_LONG_CONSTANT("ARES_T_A6", T_A6, CONST_CS|CONST_PERSISTENT);
2194 #endif
2195 #ifdef T_DNAME
2196 /* (39) Non-terminal DNAME (for IPv6) */
2197 REGISTER_LONG_CONSTANT("ARES_T_DNAME", T_DNAME, CONST_CS|CONST_PERSISTENT);
2198 #endif
2199 #ifdef T_SINK
2200 /* (40) Kitchen sink (experimentatl) */
2201 REGISTER_LONG_CONSTANT("ARES_T_SINK", T_SINK, CONST_CS|CONST_PERSISTENT);
2202 #endif
2203 #ifdef T_OPT
2204 /* (41) EDNS0 option (meta-RR) */
2205 REGISTER_LONG_CONSTANT("ARES_T_OPT", T_OPT, CONST_CS|CONST_PERSISTENT);
2206 #endif
2207 #ifdef T_TSIG
2208 /* (250) Transaction signature. */
2209 REGISTER_LONG_CONSTANT("ARES_T_TSIG", T_TSIG, CONST_CS|CONST_PERSISTENT);
2210 #endif
2211 #ifdef T_IXFR
2212 /* (251) Incremental zone transfer. */
2213 REGISTER_LONG_CONSTANT("ARES_T_IXFR", T_IXFR, CONST_CS|CONST_PERSISTENT);
2214 #endif
2215 #ifdef T_AXFR
2216 /* (252) Transfer zone of authority. */
2217 REGISTER_LONG_CONSTANT("ARES_T_AXFR", T_AXFR, CONST_CS|CONST_PERSISTENT);
2218 #endif
2219 #ifdef T_MAILB
2220 /* (253) Transfer mailbox records. */
2221 REGISTER_LONG_CONSTANT("ARES_T_MAILB", T_MAILB, CONST_CS|CONST_PERSISTENT);
2222 #endif
2223 #ifdef T_MAILA
2224 /* (254) Transfer mail agent records. */
2225 REGISTER_LONG_CONSTANT("ARES_T_MAILA", T_MAILA, CONST_CS|CONST_PERSISTENT);
2226 #endif
2227 #ifdef T_ANY
2228 /* (255) Wildcard match. */
2229 REGISTER_LONG_CONSTANT("ARES_T_ANY", T_ANY, CONST_CS|CONST_PERSISTENT);
2230 #endif
2231
2232 /*
2233 * ns_c (dnsclass) constants (arpa/nameser.h)
2234 */
2235
2236 #ifdef C_IN
2237 /* (1) Internet. */
2238 REGISTER_LONG_CONSTANT("ARES_C_IN", C_IN, CONST_CS|CONST_PERSISTENT);
2239 #endif
2240 #ifdef C_2
2241 /* (2) unallocated/unsupported. */
2242 REGISTER_LONG_CONSTANT("ARES_C_2", C_2, CONST_CS|CONST_PERSISTENT);
2243 #endif
2244 #ifdef C_CHAOS
2245 /* (3) MIT Chaos-net. */
2246 REGISTER_LONG_CONSTANT("ARES_C_CHAOS", C_CHAOS, CONST_CS|CONST_PERSISTENT);
2247 #endif
2248 #ifdef C_HS
2249 /* (4) MIT Hesiod. */
2250 REGISTER_LONG_CONSTANT("ARES_C_HS", C_HS, CONST_CS|CONST_PERSISTENT);
2251 #endif
2252 #ifdef C_NONE
2253 /* (254) for prereq. sections in update requests */
2254 REGISTER_LONG_CONSTANT("ARES_C_NONE", C_NONE, CONST_CS|CONST_PERSISTENT);
2255 #endif
2256 #ifdef C_ANY
2257 /* (255) Wildcard match. */
2258 REGISTER_LONG_CONSTANT("ARES_C_ANY", C_ANY, CONST_CS|CONST_PERSISTENT);
2259 #endif
2260
2261 le_ares = zend_register_list_destructors_ex(php_ares_le_dtor, NULL, PHP_ARES_LE_NAME, module_number);
2262 le_ares_query = zend_register_list_destructors_ex(php_ares_query_le_dtor, NULL, PHP_ARES_QUERY_LE_NAME, module_number);
2263
2264 return SUCCESS;
2265 }
2266 /* }}} */
2267
2268 /* {{{ PHP_MSHUTDOWN_FUNCTION */
2269 static PHP_MSHUTDOWN_FUNCTION(ares)
2270 {
2271 #ifdef HAVE_ARES_LIBRARY_CLEANUP
2272 ares_library_cleanup();
2273 #endif
2274 return SUCCESS;
2275 }
2276 /* }}} */
2277
2278 /* {{{ PHP_MINFO_FUNCTION */
2279 static PHP_MINFO_FUNCTION(ares)
2280 {
2281 php_info_print_table_start();
2282 php_info_print_table_header(2, "AsyncResolver support", "enabled");
2283 php_info_print_table_row(2, "Version", PHP_ARES_VERSION);
2284 php_info_print_table_end();
2285
2286 php_info_print_table_start();
2287 php_info_print_table_header(3, "Used Library", "compiled", "linked");
2288 php_info_print_table_row(3,
2289 PHP_ARES_LIBNAME,
2290 #ifdef ARES_VERSION_STR
2291 ARES_VERSION_STR,
2292 #else
2293 "unkown",
2294 #endif
2295 #ifdef HAVE_ARES_VERSION
2296 ares_version(NULL)
2297 #else
2298 "unkown"
2299 #endif
2300 );
2301 php_info_print_table_end();
2302 }
2303 /* }}} */
2304
2305 #ifdef ZEND_ENGINE_2
2306 ZEND_BEGIN_ARG_INFO(ai_ares_select, 0)
2307 ZEND_ARG_PASS_INFO(1)
2308 ZEND_ARG_PASS_INFO(1)
2309 ZEND_ARG_PASS_INFO(0)
2310 ZEND_END_ARG_INFO();
2311
2312 ZEND_BEGIN_ARG_INFO(ai_ares_result, 0)
2313 ZEND_ARG_PASS_INFO(0)
2314 ZEND_ARG_PASS_INFO(1)
2315 ZEND_ARG_PASS_INFO(1)
2316 ZEND_END_ARG_INFO();
2317
2318 ZEND_BEGIN_ARG_INFO(ai_ares_fds, 0)
2319 ZEND_ARG_PASS_INFO(0)
2320 ZEND_ARG_PASS_INFO(1)
2321 ZEND_ARG_PASS_INFO(1)
2322 ZEND_END_ARG_INFO();
2323 #else
2324 static unsigned char ai_ares_select[] = {3, BYREF_FORCE, BYREF_FORCE, BYREF_NONE};
2325 static unsigned char ai_ares_result[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
2326 static unsigned char ai_ares_fds[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
2327 #endif
2328
2329 /* {{{ ares_functions[] */
2330 zend_function_entry ares_functions[] = {
2331 #ifdef HAVE_ARES_VERSION
2332 PHP_FE(ares_version, NULL)
2333 #endif
2334 PHP_FE(ares_init, NULL)
2335 PHP_FE(ares_destroy, NULL)
2336 PHP_FE(ares_strerror, NULL)
2337 #ifdef HAVE_ARES_CANCEL
2338 PHP_FE(ares_cancel, NULL)
2339 #endif
2340 PHP_FE(ares_search, NULL)
2341 PHP_FE(ares_query, NULL)
2342 PHP_FE(ares_send, NULL)
2343 PHP_FE(ares_mkquery, NULL)
2344 PHP_FE(ares_gethostbyname, NULL)
2345 PHP_FE(ares_gethostbyaddr, NULL)
2346 #ifdef HAVE_ARES_GETNAMEINFO
2347 PHP_FE(ares_getnameinfo, NULL)
2348 #endif
2349 PHP_FE(ares_result, ai_ares_result)
2350 PHP_FE(ares_packet, NULL)
2351 PHP_FE(ares_process_all, NULL)
2352 PHP_FE(ares_process_once, NULL)
2353 PHP_FE(ares_process, NULL)
2354 PHP_FE(ares_select, ai_ares_select)
2355 PHP_FE(ares_fds, ai_ares_fds)
2356 PHP_FE(ares_timeout, NULL)
2357 #ifdef HAVE_ARES_SET_LOCAL_DEV
2358 PHP_FE(ares_set_local_dev, NULL)
2359 #endif
2360 #ifdef HAVE_ARES_SET_LOCAL_IP4
2361 PHP_FE(ares_set_local_ip4, NULL)
2362 #endif
2363 #ifdef HAVE_ARES_SET_LOCAL_IP6
2364 PHP_FE(ares_set_local_ip6, NULL)
2365 #endif
2366 {NULL, NULL, NULL}
2367 };
2368 /* }}} */
2369
2370 /* {{{ ares_module_entry */
2371 zend_module_entry ares_module_entry = {
2372 STANDARD_MODULE_HEADER,
2373 "ares",
2374 ares_functions,
2375 PHP_MINIT(ares),
2376 PHP_MSHUTDOWN(ares),
2377 NULL,
2378 NULL,
2379 PHP_MINFO(ares),
2380 PHP_ARES_VERSION,
2381 STANDARD_MODULE_PROPERTIES
2382 };
2383 /* }}} */
2384
2385 #ifdef COMPILE_DL_ARES
2386 ZEND_GET_MODULE(ares)
2387 #endif
2388
2389 /*
2390 * Local variables:
2391 * tab-width: 4
2392 * c-basic-offset: 4
2393 * End:
2394 * vim600: noet sw=4 ts=4 fdm=marker
2395 * vim<600: noet sw=4 ts=4
2396 */