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