* Implemented reply parsers for A, NS, PTR, CNAME, MX, SOA, SRV, TXT messages
[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 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(result), php_ares_T_names[type], strlen(php_ares_T_names[type])+1, (void *) &entry_ptr)) {
742 add_next_index_zval(*entry_ptr, entry);
743 } else {
744 zval *array;
745
746 MAKE_STD_ZVAL(array);
747 array_init(array);
748 add_next_index_zval(array, entry);
749 add_assoc_zval(result, php_ares_T_names[type], array);
750 }*/
751 }
752 }
753
754 return SUCCESS;
755 }
756 /* }}} */
757
758 /* {{{ callbacks */
759 static void php_ares_callback_func_old(void *aq, int status, unsigned char *abuf, int alen)
760 {
761 php_ares_query *q = (php_ares_query *) aq;
762 zval *params[4], *retval, *parsed = NULL;
763 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
764
765 q->error = status;
766 if (abuf) {
767 q->result.std.buf = estrndup((char *) abuf, alen);
768 q->result.std.len = alen;
769
770 MAKE_STD_ZVAL(parsed);
771 ZVAL_NULL(parsed);
772 if (SUCCESS == php_ares_parse(abuf, alen, parsed)) {
773 q->result.std.arr = parsed;
774 } else {
775 zval_ptr_dtor(&parsed);
776 parsed = NULL;
777 }
778 }
779
780 if (q->callback) {
781 MAKE_STD_ZVAL(retval);
782 MAKE_STD_ZVAL(params[0]);
783 MAKE_STD_ZVAL(params[1]);
784 MAKE_STD_ZVAL(params[2]);
785 ZVAL_NULL(retval);
786 zend_list_addref(q->id);
787 Z_LVAL_P(params[0]) = q->id;
788 Z_TYPE_P(params[0]) = IS_RESOURCE;
789 ZVAL_LONG(params[1], status);
790 ZVAL_STRINGL(params[2], (char *) abuf, alen, 1);
791
792 if (parsed) {
793 ADDREF(parsed);
794 params[3] = parsed;
795 }
796
797 q->ares->in_callback = 1;
798 call_user_function(EG(function_table), NULL, q->callback, retval, parsed ? 4 : 3, params TSRMLS_CC);
799 q->ares->in_callback = 0;
800
801 zval_ptr_dtor(&retval);
802 zval_ptr_dtor(&params[0]);
803 zval_ptr_dtor(&params[1]);
804 zval_ptr_dtor(&params[2]);
805
806 if (parsed) {
807 zval_ptr_dtor(&params[3]);
808 }
809 }
810 }
811
812 static void php_ares_host_callback_func_old(void *aq, int status, struct hostent *hostent)
813 {
814 php_ares_query *q = (php_ares_query *) aq;
815 zval *params[3], *retval;
816 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
817
818 q->error = status;
819 if (hostent) {
820 php_ares_hostent_copy(hostent, &q->result.host);
821 }
822
823 if (q->callback) {
824 MAKE_STD_ZVAL(retval);
825 MAKE_STD_ZVAL(params[0]);
826 MAKE_STD_ZVAL(params[1]);
827 MAKE_STD_ZVAL(params[2]);
828 ZVAL_NULL(retval);
829 zend_list_addref(q->id);
830 Z_LVAL_P(params[0]) = q->id;
831 Z_TYPE_P(params[0]) = IS_RESOURCE;
832 ZVAL_LONG(params[1], status);
833 object_init(params[2]);
834 php_ares_hostent_to_struct(hostent, HASH_OF(params[2]));
835
836 q->ares->in_callback = 1;
837 call_user_function(EG(function_table), NULL, q->callback, retval, 3, params TSRMLS_CC);
838 q->ares->in_callback = 0;
839
840 zval_ptr_dtor(&retval);
841 zval_ptr_dtor(&params[0]);
842 zval_ptr_dtor(&params[1]);
843 zval_ptr_dtor(&params[2]);
844 }
845 }
846
847 #ifdef HAVE_ARES_GETNAMEINFO
848 static void php_ares_nameinfo_callback_func_old(void *aq, int status, char *node, char *service)
849 {
850 php_ares_query *q = (php_ares_query *) aq;
851 zval *params[4], *retval;
852 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
853
854 q->error = status;
855 if (node) {
856 q->result.ninfo.node = estrdup(node);
857 }
858 if (service) {
859 q->result.ninfo.service = estrdup(service);
860 }
861
862 if (q->callback) {
863 MAKE_STD_ZVAL(retval);
864 MAKE_STD_ZVAL(params[0]);
865 MAKE_STD_ZVAL(params[1]);
866 MAKE_STD_ZVAL(params[2]);
867 MAKE_STD_ZVAL(params[3]);
868 ZVAL_NULL(retval);
869 zend_list_addref(q->id);
870 Z_LVAL_P(params[0]) = q->id;
871 Z_TYPE_P(params[0]) = IS_RESOURCE;
872 ZVAL_LONG(params[1], status);
873 if (node) {
874 ZVAL_STRING(params[2], node, 1);
875 } else {
876 ZVAL_NULL(params[2]);
877 }
878 if (service) {
879 ZVAL_STRING(params[3], service, 1);
880 } else {
881 ZVAL_NULL(params[3]);
882 }
883
884 q->ares->in_callback = 1;
885 call_user_function(EG(function_table), NULL, q->callback, retval, 4, params TSRMLS_CC);
886 q->ares->in_callback = 0;
887
888 zval_ptr_dtor(&retval);
889 zval_ptr_dtor(&params[0]);
890 zval_ptr_dtor(&params[1]);
891 zval_ptr_dtor(&params[2]);
892 zval_ptr_dtor(&params[3]);
893 }
894 }
895 #endif
896
897 #if PHP_ARES_NEW_CALLBACK_API
898 # define php_ares_callback_func php_ares_callback_func_new
899 static void php_ares_callback_func_new(void *aq, int status, int timeouts, unsigned char *abuf, int alen)
900 {
901 php_ares_callback_func_old(aq, status, abuf, alen);
902 }
903
904 # define php_ares_host_callback_func php_ares_host_callback_func_new
905 static void php_ares_host_callback_func_new(void *aq, int status, int timeouts, struct hostent *hostent)
906 {
907 php_ares_host_callback_func_old(aq, status, hostent);
908 }
909
910 # ifdef HAVE_ARES_GETNAMEINFO
911 # define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_new
912 static void php_ares_nameinfo_callback_func_new(void *aq, int status, int timeouts, char *node, char *service)
913 {
914 php_ares_nameinfo_callback_func_old(aq, status, node, service);
915 }
916 # endif
917
918 #else
919 # define php_ares_callback_func php_ares_callback_func_old
920 # define php_ares_host_callback_func php_ares_host_callback_func_old
921 # ifdef HAVE_ARES_GETNAMEINFO
922 # define php_ares_nameinfo_callback_func php_ares_nameinfo_callback_func_old
923 # endif
924 #endif
925 /* }}} */
926
927 local struct timeval *php_ares_timeout(php_ares *ares, long max_timeout, struct timeval *tv_buf) /* {{{ */
928 {
929 struct timeval maxtv;
930
931 if (max_timeout > -1) {
932 maxtv.tv_sec = max_timeout / 1000;
933 maxtv.tv_usec = max_timeout % (max_timeout * 1000);
934 }
935
936 return ares_timeout(ares->channel, max_timeout > -1 ? &maxtv : NULL, tv_buf);
937 }
938 /* }}} */
939
940 local int php_ares_process(php_ares *ares, long max_timeout) /* {{{ */
941 {
942 int nfds;
943 fd_set R, W;
944 struct timeval tv;
945
946 FD_ZERO(&R);
947 FD_ZERO(&W);
948
949 if ((nfds = ares_fds(ares->channel, &R, &W))) {
950 if (0 < select(nfds, &R, &W, NULL, php_ares_timeout(ares, max_timeout, &tv))) {
951 ares_process(ares->channel, &R, &W);
952 }
953 }
954
955 return nfds;
956 }
957 /* }}} */
958
959 local int php_ares_publish_fds(fd_set *R, fd_set *W, zval *r, zval *w) /* {{{ */
960 {
961 int i, nfds = 0;
962
963 for (i = 0; i < FD_SETSIZE; ++i) {
964 if (FD_ISSET(i, R)) {
965 add_next_index_long(r, i);
966 if (i > nfds) {
967 nfds = i;
968 }
969 }
970 }
971
972 for (i = 0; i < FD_SETSIZE; ++i) {
973 if (FD_ISSET(i, W)) {
974 add_next_index_long(w, i);
975 if (i > nfds) {
976 nfds = i;
977 }
978 }
979 }
980
981 return nfds ? nfds + 1 : 0;
982 }
983 /* }}} */
984
985 local int php_ares_extract_fds(zval *r, zval *w, fd_set *R, fd_set *W) /* {{{ */
986 {
987 zval **fd;
988 int nfds = 0;
989
990 if (r && zend_hash_num_elements(Z_ARRVAL_P(r))) {
991 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(r));
992 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(r), (void *) &fd);
993 zend_hash_move_forward(Z_ARRVAL_P(r))) {
994 if (Z_TYPE_PP(fd) == IS_LONG) {
995 FD_SET(Z_LVAL_PP(fd), R);
996 if (Z_LVAL_PP(fd) > nfds) {
997 nfds = Z_LVAL_PP(fd);
998 }
999 }
1000 }
1001 }
1002
1003 if (w && zend_hash_num_elements(Z_ARRVAL_P(w))) {
1004 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(w));
1005 SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(w), (void *) &fd);
1006 zend_hash_move_forward(Z_ARRVAL_P(w))) {
1007 if (Z_TYPE_PP(fd) == IS_LONG) {
1008 FD_SET(Z_LVAL_PP(fd), W);
1009 if (Z_LVAL_PP(fd) > nfds) {
1010 nfds = Z_LVAL_PP(fd);
1011 }
1012 }
1013 }
1014 }
1015
1016 return nfds ? nfds + 1 : 0;
1017 }
1018 /* }}} */
1019
1020 static void php_ares_query_llist_dtor(void *entry)
1021 {
1022 php_ares_query *q = *(php_ares_query **) entry;
1023 TSRMLS_FETCH_FROM_CTX(q->ares->tsrm_ls);
1024 zend_list_delete(q->id);
1025 }
1026
1027 #ifdef HAVE_ARES_VERSION
1028 /* {{{ proto string ares_version()
1029 Get libares version */
1030 static PHP_FUNCTION(ares_version)
1031 {
1032 if (ZEND_NUM_ARGS()) {
1033 WRONG_PARAM_COUNT;
1034 }
1035
1036 RETURN_STRING(estrdup(ares_version(NULL)), 0);
1037 }
1038 /* }}} */
1039 #endif
1040
1041 /* {{{ proto resource ares_init([array options])
1042 Create an ares resource */
1043 static PHP_FUNCTION(ares_init)
1044 {
1045 zval *opt_array = NULL;
1046 php_ares *ares = NULL;
1047 int err;
1048
1049 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &opt_array)) {
1050 RETURN_FALSE;
1051 }
1052
1053 ares = emalloc(sizeof(php_ares));
1054 TSRMLS_SET_CTX(ares->tsrm_ls);
1055 zend_llist_init(&ares->queries, sizeof(php_ares_query *), (llist_dtor_func_t) php_ares_query_llist_dtor, 0);
1056 php_ares_options_ctor(&ares->options, opt_array ? Z_ARRVAL_P(opt_array) : NULL);
1057
1058 if (ARES_SUCCESS != (err = ares_init_options(&ares->channel, &ares->options.strct, ares->options.flags))) {
1059 php_ares_options_dtor(&ares->options);
1060 zend_llist_destroy(&ares->queries);
1061 efree(ares);
1062 RETURN_ARES_ERROR(err);
1063 }
1064
1065 ZEND_REGISTER_RESOURCE(return_value, ares, le_ares);
1066 }
1067 /* }}} */
1068
1069 /* {{{ proto void ares_destroy(resource ares)
1070 Destroy the ares handle */
1071 static PHP_FUNCTION(ares_destroy)
1072 {
1073 zval *rsrc;
1074 php_ares *ares;
1075
1076 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1077 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1078 if (ares->in_callback) {
1079 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy ares handle while in callback");
1080 } else {
1081 zend_list_delete(Z_LVAL_P(rsrc));
1082 }
1083 }
1084 }
1085 /* }}} */
1086
1087 /* {{{ proto string ares_strerror(int status)
1088 Get description of status code */
1089 static PHP_FUNCTION(ares_strerror)
1090 {
1091 long err;
1092 #ifdef HAVE_OLD_ARES_STRERROR
1093 char *__tmp = NULL;
1094 const char *__err;
1095 #endif
1096
1097 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &err)) {
1098 RETURN_FALSE;
1099 }
1100
1101 #ifdef HAVE_OLD_ARES_STRERROR
1102 __err = ares_strerror(err, &__tmp);
1103 RETVAL_STRING(estrdup(__err), 0);
1104 if (__tmp) {
1105 ares_free_errmem(__tmp);
1106 }
1107 #else
1108 RETURN_STRING(estrdup(ares_strerror(err)), 0);
1109 #endif
1110 }
1111 /* }}} */
1112
1113 /* {{{ proto string ares_mkquery(string name, int dnsclass, int type, int id, int rd)
1114 Compose a custom query */
1115 static PHP_FUNCTION(ares_mkquery)
1116 {
1117 char *name_str, *query_str;
1118 int name_len, query_len, err;
1119 long dnsclass, type, id, rd;
1120
1121 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &name_str, &name_len, &dnsclass, &type, &id, &rd)) {
1122 RETURN_FALSE;
1123 }
1124
1125 if (ARES_SUCCESS != (err = ares_mkquery(name_str, dnsclass, type, id, rd, (unsigned char **) &query_str, &query_len))) {
1126 RETURN_ARES_ERROR(err);
1127 }
1128 RETVAL_STRINGL(query_str, query_len, 1);
1129 ares_free_string(query_str);
1130 }
1131 /* }}} */
1132
1133 /* {{{ proto resource ares_search(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
1134 Issue a domain search for name */
1135 static PHP_FUNCTION(ares_search)
1136 {
1137 zval *rsrc, *cb = NULL;
1138 php_ares *ares;
1139 php_ares_query *query;
1140 char *name;
1141 int name_len;
1142 long dnsclass = C_IN, type = T_A;
1143
1144 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
1145 RETURN_FALSE;
1146 }
1147 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1148
1149 if (cb && !IS_CALLABLE(cb, 0, NULL)) {
1150 RETURN_ARES_CB_ERROR("second");
1151 }
1152
1153 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1154 php_ares_query_rsrc(query, return_value);
1155 php_ares_query_pckt(query, PHP_ARES_PCKT_SEARCH, name, name_len, type, dnsclass);
1156 ares_search(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
1157 }
1158 /* }}} */
1159
1160 /* {{{ proto resource ares_query(resource ares, mixed callback, string name[, int type = ARES_T_A[, int dnsclass = ARES_C_IN]])
1161 Issue a single DNS query */
1162 static PHP_FUNCTION(ares_query)
1163 {
1164 zval *rsrc, *cb = NULL;
1165 php_ares *ares;
1166 php_ares_query *query;
1167 char *name;
1168 int name_len;
1169 long dnsclass = C_IN, type = T_A;
1170
1171 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|ll", &rsrc, &cb, &name, &name_len, &type, &dnsclass)) {
1172 RETURN_FALSE;
1173 }
1174 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1175
1176 if (cb && !IS_CALLABLE(cb, 0, NULL)) {
1177 RETURN_ARES_CB_ERROR("second");
1178 }
1179
1180 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1181 php_ares_query_rsrc(query, return_value);
1182 php_ares_query_pckt(query, PHP_ARES_PCKT_QUERY, name, name_len, type, dnsclass);
1183 ares_query(ares->channel, name, dnsclass, type, php_ares_callback_func, query);
1184 }
1185 /* }}} */
1186
1187 /* {{{ proto resource ares_send(resource ares, mixed callback, string buf)
1188 Send custom query */
1189 static PHP_FUNCTION(ares_send)
1190 {
1191 zval *rsrc, *cb = NULL;
1192 php_ares *ares;
1193 php_ares_query *query;
1194 char *buf;
1195 int len;
1196
1197 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s", &rsrc, &cb, &buf, &len)) {
1198 RETURN_FALSE;
1199 }
1200 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1201
1202 if (cb && !IS_CALLABLE(cb, 0, NULL)) {
1203 RETURN_ARES_CB_ERROR("second");
1204 }
1205
1206 query = php_ares_query_ctor(NULL, PHP_ARES_CB_STD, ares, cb);
1207 php_ares_query_rsrc(query, return_value);
1208 php_ares_query_pckt(query, PHP_ARES_PCKT_SEND, buf, len);
1209 ares_send(ares->channel, (const unsigned char *) buf, len, php_ares_callback_func, query);
1210 }
1211 /* }}} */
1212
1213 /* {{{ proto resource ares_gethostbyname(resource ares, mixed callback, string name[, int family = AF_INET])
1214 Get host by name */
1215 static PHP_FUNCTION(ares_gethostbyname)
1216 {
1217 zval *rsrc, *cb = NULL;
1218 php_ares *ares;
1219 php_ares_query *query;
1220 char *name;
1221 int name_len;
1222 long family = AF_INET;
1223
1224 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &name, &name_len, &family)) {
1225 RETURN_FALSE;
1226 }
1227 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1228
1229 if (cb && !IS_CALLABLE(cb, 0, NULL)) {
1230 RETURN_ARES_CB_ERROR("second");
1231 }
1232
1233 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
1234 php_ares_query_rsrc(query, return_value);
1235 php_ares_query_pckt(query, PHP_ARES_PCKT_HNAME, name, name_len, family);
1236 ares_gethostbyname(ares->channel, name, family, php_ares_host_callback_func, query);
1237 }
1238 /* }}} */
1239
1240 /* {{{ proto resource ares_gethostbyaddr(resuorce ares, mixed callback, string address[, int family = ARES_AF_INET])
1241 Get host by address */
1242 static PHP_FUNCTION(ares_gethostbyaddr)
1243 {
1244 zval *rsrc, *cb = NULL;
1245 php_ares *ares;
1246 php_ares_query *query;
1247 char *addr;
1248 int addr_len;
1249 long family = AF_INET;
1250 void *sa;
1251 int sa_len;
1252
1253 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!s|l", &rsrc, &cb, &addr, &addr_len, &family)) {
1254 RETURN_FALSE;
1255 }
1256 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1257
1258 if (cb && !IS_CALLABLE(cb, 0, NULL)) {
1259 PHP_ARES_CB_ERROR("second");
1260 RETURN_FALSE;
1261 }
1262
1263 switch (family) {
1264 case AF_INET:
1265 sa = emalloc(sa_len = sizeof(struct in_addr));
1266 break;
1267 case AF_INET6:
1268 sa = emalloc(sa_len = sizeof(struct in6_addr));
1269 break;
1270 default:
1271 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither ARES_AF_INET nor ARES_AF_INET6");
1272 RETURN_FALSE;
1273 break;
1274 }
1275
1276 if (1 > inet_pton(family, addr, sa)) {
1277 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1278 RETVAL_FALSE;
1279 } else {
1280 query = php_ares_query_ctor(NULL, PHP_ARES_CB_HOST, ares, cb);
1281 php_ares_query_rsrc(query, return_value);
1282 php_ares_query_pckt(query, PHP_ARES_PCKT_HADDR, addr, addr_len, family);
1283 ares_gethostbyaddr(ares->channel, sa, sa_len, family, php_ares_host_callback_func, query);
1284 }
1285 efree(sa);
1286 }
1287 /* }}} */
1288
1289 #ifdef HAVE_ARES_GETNAMEINFO
1290 /* {{{ proto resource ares_getnameinfo(resource ares, mixed callback, int flags, string addr[, int family = ARES_AF_INET[, int port = 0]])
1291 Get name info */
1292 static PHP_FUNCTION(ares_getnameinfo)
1293 {
1294 zval *rsrc, *cb = NULL;
1295 php_ares *ares;
1296 php_ares_query *query;
1297 char *addr;
1298 int addr_len;
1299 long flags, port = 0, family = AF_INET;
1300 struct sockaddr *sa;
1301 struct sockaddr_in *in;
1302 struct sockaddr_in6 *in6;
1303 int sa_len;
1304
1305 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz!ls|ll", &rsrc, &cb, &flags, &addr, &addr_len, &family, &port)) {
1306 RETURN_FALSE;
1307 }
1308 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1309
1310 if (cb && !IS_CALLABLE(cb, 0, NULL)) {
1311 PHP_ARES_CB_ERROR("second");
1312 RETURN_FALSE;
1313 }
1314
1315 RETVAL_TRUE;
1316 switch (family) {
1317 case AF_INET:
1318 in = ecalloc(1, sa_len = sizeof(struct sockaddr_in));
1319 in->sin_family = AF_INET;
1320 in->sin_port = htons((unsigned short) port);
1321 if (1 > inet_pton(in->sin_family, addr, &in->sin_addr)) {
1322 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1323 RETVAL_FALSE;
1324 }
1325 sa = (struct sockaddr *) in;
1326 break;
1327 case AF_INET6:
1328 in6 = ecalloc(1, sa_len = sizeof(struct sockaddr_in6));
1329 in6->sin6_family = AF_INET6;
1330 in6->sin6_port = htons((unsigned short) port);
1331 if (1 > inet_pton(in6->sin6_family, addr, &in6->sin6_addr)) {
1332 php_error_docref(NULL TSRMLS_CC, E_WARNING, "inet_pton('%s') failed", addr);
1333 RETVAL_FALSE;
1334 }
1335 sa = (struct sockaddr *) in6;
1336 break;
1337 default:
1338 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter family is neither AF_INET nor AF_INET6");
1339 RETURN_FALSE;
1340 break;
1341 }
1342
1343 if (Z_BVAL_P(return_value)) {
1344 query = php_ares_query_ctor(NULL, PHP_ARES_CB_NINFO, ares, cb);
1345 php_ares_query_rsrc(query, return_value);
1346 php_ares_query_pckt(query, PHP_ARES_PCKT_NINFO, flags, addr, addr_len, family, port);
1347 ares_getnameinfo(ares->channel, sa, sa_len, flags, php_ares_nameinfo_callback_func, query);
1348 }
1349 efree(sa);
1350 }
1351 /* }}} */
1352 #endif
1353
1354 /* {{{ proto mixed ares_result(resource query, int &errno, string &error)
1355 Check a query for its result */
1356 static PHP_FUNCTION(ares_result)
1357 {
1358 zval *rsrc, *zerrno = NULL, *zerror = NULL;
1359 php_ares_query *query;
1360
1361 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|zz", &rsrc, &zerrno, &zerror)) {
1362 RETURN_FALSE;
1363 }
1364 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1365
1366 if (zerrno) {
1367 zval_dtor(zerrno);
1368 ZVAL_LONG(zerrno, query->error);
1369 }
1370 if (zerror) {
1371 zval_dtor(zerror);
1372 ZVAL_NULL(zerror);
1373 }
1374
1375 switch (query->error) {
1376 case 0:
1377 switch (query->type) {
1378 case PHP_ARES_CB_STD:
1379 if (query->result.std.arr) {
1380 RETVAL_ZVAL(query->result.std.arr, 1, 0);
1381 } else {
1382 RETVAL_STRINGL(query->result.std.buf, query->result.std.len, 1);
1383 }
1384 break;
1385 case PHP_ARES_CB_HOST:
1386 object_init(return_value);
1387 php_ares_hostent_to_struct(&query->result.host, HASH_OF(return_value));
1388 break;
1389 case PHP_ARES_CB_NINFO:
1390 object_init(return_value);
1391 add_property_string(return_value, "node", query->result.ninfo.node ? query->result.ninfo.node : "", 1);
1392 add_property_string(return_value, "service", query->result.ninfo.service ? query->result.ninfo.service : "", 1);
1393 break;
1394 }
1395 break;
1396 case -1:
1397 RETVAL_FALSE;
1398 break;
1399 default:
1400 if (zerror) {
1401 #ifdef HAVE_OLD_ARES_STRERROR
1402 char *__tmp = NULL;
1403 const char *__err = ares_strerror(query->error, &__tmp);
1404 ZVAL_STRING(zerror, estrdup(__err), 0);
1405 if (__tmp) ares_free_errmem(__tmp);
1406 #else
1407 ZVAL_STRING(zerror, estrdup(ares_strerror(query->error)), 0);
1408 #endif
1409 }
1410 RETVAL_FALSE;
1411 break;
1412 }
1413 }
1414 /* }}} */
1415
1416 /* {{{ proto object ares_packet(resource query)
1417 Check a query for its question packet */
1418 static PHP_FUNCTION(ares_packet)
1419 {
1420 zval *rsrc, *prop;
1421 php_ares_query *query;
1422
1423 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1424 RETURN_FALSE;
1425 }
1426 ZEND_FETCH_RESOURCE(query, php_ares_query *, &rsrc, -1, PHP_ARES_QUERY_LE_NAME, le_ares_query);
1427
1428 object_init(return_value);
1429 add_property_long(return_value, "type", query->packet.type);
1430 add_property_null(return_value, "search");
1431 add_property_null(return_value, "query");
1432 add_property_null(return_value, "send");
1433 add_property_null(return_value, "gethostbyname");
1434 add_property_null(return_value, "gethostbyaddr");
1435 add_property_null(return_value, "getnameinfo");
1436 MAKE_STD_ZVAL(prop);
1437
1438 switch (query->packet.type) {
1439 case PHP_ARES_PCKT_SEARCH:
1440 object_init(prop);
1441 add_property_stringl(prop, "name", query->packet.data.search.name, query->packet.data.search.name_len, 1);
1442 add_property_long(prop, "type", query->packet.data.search.type);
1443 add_property_long(prop, "dnsclass", query->packet.data.search.dnsclass);
1444 add_property_zval(return_value, "search", prop);
1445 break;
1446
1447 case PHP_ARES_PCKT_QUERY:
1448 object_init(prop);
1449 add_property_stringl(prop, "name", query->packet.data.query.name, query->packet.data.query.name_len, 1);
1450 add_property_long(prop, "type", query->packet.data.query.type);
1451 add_property_long(prop, "dnsclass", query->packet.data.query.dnsclass);
1452 add_property_zval(return_value, "query", prop);
1453 break;
1454
1455 case PHP_ARES_PCKT_SEND:
1456 ZVAL_STRINGL(prop, query->packet.data.send.buf, query->packet.data.send.len, 1);
1457 add_property_zval(return_value, "send", prop);
1458 break;
1459
1460 case PHP_ARES_PCKT_HNAME:
1461 object_init(prop);
1462 add_property_stringl(prop, "name", query->packet.data.hname.name, query->packet.data.hname.name_len, 1);
1463 add_property_long(prop, "family", query->packet.data.hname.family);
1464 add_property_zval(return_value, "gethostbyname", prop);
1465 break;
1466
1467 case PHP_ARES_PCKT_HADDR:
1468 object_init(prop);
1469 add_property_stringl(prop, "addr", query->packet.data.haddr.addr, query->packet.data.haddr.addr_len, 1);
1470 add_property_long(prop, "family", query->packet.data.haddr.family);
1471 add_property_zval(return_value, "gethostbyaddr", prop);
1472 break;
1473
1474 case PHP_ARES_PCKT_NINFO:
1475 object_init(prop);
1476 add_property_long(prop, "flags", query->packet.data.ninfo.flags);
1477 add_property_stringl(prop, "addr", query->packet.data.ninfo.addr, query->packet.data.ninfo.addr_len, 1);
1478 add_property_long(prop, "family", query->packet.data.ninfo.family);
1479 add_property_long(prop, "port", query->packet.data.ninfo.port);
1480 add_property_zval(return_value, "getnameinfo", prop);
1481 break;
1482 }
1483
1484 zval_ptr_dtor(&prop);
1485 }
1486 /* }}} */
1487
1488 #ifdef HAVE_ARES_CANCEL
1489 /* {{{ proto void ares_cancel(resource ares)
1490 Cancel pending queries */
1491 static PHP_FUNCTION(ares_cancel)
1492 {
1493 zval *rsrc;
1494 php_ares *ares;
1495
1496 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &rsrc)) {
1497 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1498 ares_cancel(ares->channel);
1499 }
1500 }
1501 /* }}} */
1502 #endif
1503
1504 /* {{{ proto void ares_process_all(resource ares[, int max_timeout_ms])
1505 Process all pending queries */
1506 static PHP_FUNCTION(ares_process_all)
1507 {
1508 zval *rsrc;
1509 php_ares *ares;
1510 long max_timeout = -1;
1511
1512 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1513 RETURN_FALSE;
1514 }
1515 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1516
1517 while (php_ares_process(ares, max_timeout));
1518 }
1519 /* }}} */
1520
1521 /* {{{ proto bool ares_process_once(resource ares[, int max_timout_ms])
1522 Process once and return whether it should be called again */
1523 static PHP_FUNCTION(ares_process_once)
1524 {
1525 zval *rsrc;
1526 php_ares *ares;
1527 long max_timeout = -1;
1528
1529 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1530 RETURN_FALSE;
1531 }
1532 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1533
1534 RETVAL_BOOL(php_ares_process(ares, max_timeout));
1535 }
1536 /* }}} */
1537
1538 /* {{{ proto void ares_process(resource ares, array read, array write)
1539 Process call */
1540 static PHP_FUNCTION(ares_process)
1541 {
1542 zval *rsrc, *read = NULL, *write = NULL;
1543 fd_set R, W;
1544 php_ares *ares;
1545
1546 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a!a!", &rsrc, &read, &write)) {
1547 RETURN_FALSE;
1548 }
1549 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1550
1551 FD_ZERO(&R);
1552 FD_ZERO(&W);
1553
1554 php_ares_extract_fds(read, write, &R, &W);
1555 ares_process(ares->channel, &R, &W);
1556 }
1557 /* }}} */
1558
1559 /* proto bool ares_select(array &read, array &write, int timeout_ms)
1560 Select call */
1561 static PHP_FUNCTION(ares_select)
1562 {
1563 zval *read = NULL, *write = NULL;
1564 fd_set R, W;
1565 int nfds;
1566 long timeout;
1567 struct timeval tv;
1568
1569 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aal", &read, &write, &timeout)) {
1570 RETURN_FALSE;
1571 }
1572
1573 if (timeout) {
1574 tv.tv_sec = timeout / 1000;
1575 tv.tv_usec = timeout % (timeout * 1000);
1576 } else {
1577 tv.tv_sec = 1;
1578 tv.tv_usec = 0;
1579 }
1580
1581 FD_ZERO(&R);
1582 FD_ZERO(&W);
1583
1584 nfds = php_ares_extract_fds(read, write, &R, &W);
1585 if (-1 < select(nfds, &R, &W, NULL, &tv)) {
1586 zend_hash_clean(Z_ARRVAL_P(read));
1587 zend_hash_clean(Z_ARRVAL_P(write));
1588 php_ares_publish_fds(&R, &W, read, write);
1589 RETURN_TRUE;
1590 }
1591 RETURN_FALSE;
1592 }
1593 /* }}} */
1594
1595 /* proto int ares_timeout(resource ares[, int max_timout_ms])
1596 Get suggested select timeout in ms */
1597 static PHP_FUNCTION(ares_timeout)
1598 {
1599 zval *rsrc;
1600 long max_timeout = -1;
1601 struct timeval tv, *tvptr;
1602 php_ares *ares;
1603
1604 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &rsrc, &max_timeout)) {
1605 RETURN_FALSE;
1606 }
1607 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1608
1609 if ((tvptr = php_ares_timeout(ares, max_timeout, &tv))) {
1610 RETURN_LONG(tvptr->tv_sec * 1000 + tvptr->tv_usec / 1000);
1611 }
1612 RETURN_LONG(0);
1613 }
1614 /* }}} */
1615
1616 /* {{{ proto int ares_fds(resource ares, array &read, array &write)
1617 Get file descriptors */
1618 static PHP_FUNCTION(ares_fds)
1619 {
1620 zval *rsrc, *read, *write;
1621 fd_set R, W;
1622 php_ares *ares;
1623
1624 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz", &rsrc, &read, &write)) {
1625 RETURN_FALSE;
1626 }
1627 ZEND_FETCH_RESOURCE(ares, php_ares *, &rsrc, -1, PHP_ARES_LE_NAME, le_ares);
1628
1629 FD_ZERO(&R);
1630 FD_ZERO(&W);
1631
1632 zval_dtor(read);
1633 zval_dtor(write);
1634 array_init(read);
1635 array_init(write);
1636 ares_fds(ares->channel, &R, &W);
1637 RETVAL_LONG(php_ares_publish_fds(&R, &W, read, write));
1638 }
1639 /* }}} */
1640
1641 static ZEND_RSRC_DTOR_FUNC(php_ares_le_dtor)
1642 {
1643 php_ares *ares = (php_ares *) rsrc->ptr;
1644
1645 ares_destroy(ares->channel);
1646 zend_llist_destroy(&ares->queries);
1647 php_ares_options_dtor(&ares->options);
1648 efree(ares);
1649 }
1650
1651 static ZEND_RSRC_DTOR_FUNC(php_ares_query_le_dtor)
1652 {
1653 php_ares_query *query = (php_ares_query *) rsrc->ptr;
1654
1655 php_ares_query_dtor(query);
1656 efree(query);
1657 }
1658
1659 /* {{{ PHP_MINIT_FUNCTION */
1660 static PHP_MINIT_FUNCTION(ares)
1661 {
1662 #ifdef HAVE_ARES_LIBRARY_INIT
1663 if (ARES_SUCCESS != ares_library_init()) {
1664 return FAILURE;
1665 }
1666 #endif
1667 #ifdef HAVE_ARES_VERSION
1668 {
1669 int ares_version_num;
1670 ares_version(&ares_version_num);
1671
1672 REGISTER_LONG_CONSTANT("ARES_VERSION", ares_version_num, CONST_PERSISTENT|CONST_CS);
1673 }
1674 #endif
1675
1676 REGISTER_LONG_CONSTANT("ARES_SUCCESS", ARES_SUCCESS, CONST_PERSISTENT|CONST_CS);
1677 REGISTER_LONG_CONSTANT("ARES_ENODATA", ARES_ENODATA, CONST_PERSISTENT|CONST_CS);
1678 REGISTER_LONG_CONSTANT("ARES_EFORMERR", ARES_EFORMERR, CONST_PERSISTENT|CONST_CS);
1679 REGISTER_LONG_CONSTANT("ARES_ESERVFAIL", ARES_ESERVFAIL, CONST_PERSISTENT|CONST_CS);
1680 REGISTER_LONG_CONSTANT("ARES_ENOTFOUND", ARES_ENOTFOUND, CONST_PERSISTENT|CONST_CS);
1681 REGISTER_LONG_CONSTANT("ARES_ENOTIMP", ARES_ENOTIMP, CONST_PERSISTENT|CONST_CS);
1682 REGISTER_LONG_CONSTANT("ARES_EREFUSED", ARES_EREFUSED, CONST_PERSISTENT|CONST_CS);
1683 REGISTER_LONG_CONSTANT("ARES_EBADQUERY", ARES_EBADQUERY, CONST_PERSISTENT|CONST_CS);
1684 REGISTER_LONG_CONSTANT("ARES_EBADNAME", ARES_EBADNAME, CONST_PERSISTENT|CONST_CS);
1685 REGISTER_LONG_CONSTANT("ARES_EBADFAMILY", ARES_EBADFAMILY, CONST_PERSISTENT|CONST_CS);
1686 REGISTER_LONG_CONSTANT("ARES_EBADRESP", ARES_EBADRESP, CONST_PERSISTENT|CONST_CS);
1687 REGISTER_LONG_CONSTANT("ARES_ECONNREFUSED", ARES_ECONNREFUSED, CONST_PERSISTENT|CONST_CS);
1688 REGISTER_LONG_CONSTANT("ARES_ETIMEOUT", ARES_ETIMEOUT, CONST_PERSISTENT|CONST_CS);
1689 REGISTER_LONG_CONSTANT("ARES_EOF", ARES_EOF, CONST_PERSISTENT|CONST_CS);
1690 REGISTER_LONG_CONSTANT("ARES_EFILE", ARES_EFILE, CONST_PERSISTENT|CONST_CS);
1691 REGISTER_LONG_CONSTANT("ARES_ENOMEM", ARES_ENOMEM, CONST_PERSISTENT|CONST_CS);
1692 REGISTER_LONG_CONSTANT("ARES_EDESTRUCTION", ARES_EDESTRUCTION, CONST_PERSISTENT|CONST_CS);
1693 #ifdef ARES_EBADSTR
1694 REGISTER_LONG_CONSTANT("ARES_EBADSTR", ARES_EBADSTR, CONST_PERSISTENT|CONST_CS);
1695 #endif
1696 #ifdef ARES_EBADFLAGS
1697 REGISTER_LONG_CONSTANT("ARES_EBADFLAGS", ARES_EBADFLAGS, CONST_PERSISTENT|CONST_CS);
1698 #endif
1699 #ifdef ARES_ENONAME
1700 REGISTER_LONG_CONSTANT("ARES_ENONAME", ARES_ENONAME, CONST_PERSISTENT|CONST_CS);
1701 #endif
1702 #ifdef ARES_EBADHINTS
1703 REGISTER_LONG_CONSTANT("ARES_EBADHINTS", ARES_EBADHINTS, CONST_PERSISTENT|CONST_CS);
1704 #endif
1705
1706 REGISTER_LONG_CONSTANT("ARES_FLAG_USEVC", ARES_FLAG_USEVC, CONST_PERSISTENT|CONST_CS);
1707 REGISTER_LONG_CONSTANT("ARES_FLAG_PRIMARY", ARES_FLAG_PRIMARY, CONST_PERSISTENT|CONST_CS);
1708 REGISTER_LONG_CONSTANT("ARES_FLAG_IGNTC", ARES_FLAG_IGNTC, CONST_PERSISTENT|CONST_CS);
1709 REGISTER_LONG_CONSTANT("ARES_FLAG_NORECURSE", ARES_FLAG_NORECURSE, CONST_PERSISTENT|CONST_CS);
1710 REGISTER_LONG_CONSTANT("ARES_FLAG_STAYOPEN", ARES_FLAG_STAYOPEN, CONST_PERSISTENT|CONST_CS);
1711 REGISTER_LONG_CONSTANT("ARES_FLAG_NOSEARCH", ARES_FLAG_NOSEARCH, CONST_PERSISTENT|CONST_CS);
1712 REGISTER_LONG_CONSTANT("ARES_FLAG_NOALIASES", ARES_FLAG_NOALIASES, CONST_PERSISTENT|CONST_CS);
1713 REGISTER_LONG_CONSTANT("ARES_FLAG_NOCHECKRESP", ARES_FLAG_NOCHECKRESP, CONST_PERSISTENT|CONST_CS);
1714
1715 /*
1716 * Address Family Constants
1717 */
1718 REGISTER_LONG_CONSTANT("ARES_AF_INET", AF_INET, CONST_PERSISTENT|CONST_CS);
1719 REGISTER_LONG_CONSTANT("ARES_AF_INET6", AF_INET6, CONST_PERSISTENT|CONST_CS);
1720
1721 /*
1722 * Name Info constants
1723 */
1724 #ifdef ARES_NI_NOFQDN
1725 REGISTER_LONG_CONSTANT("ARES_NI_NOFQDN", ARES_NI_NOFQDN, CONST_PERSISTENT|CONST_CS);
1726 #endif
1727 #ifdef ARES_NI_NUMERICHOST
1728 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICHOST", ARES_NI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
1729 #endif
1730 #ifdef ARES_NI_NAMEREQD
1731 REGISTER_LONG_CONSTANT("ARES_NI_NAMEREQD", ARES_NI_NAMEREQD, CONST_PERSISTENT|CONST_CS);
1732 #endif
1733 #ifdef ARES_NI_NUMERICSERV
1734 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSERV", ARES_NI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
1735 #endif
1736 #ifdef ARES_NI_DGRAM
1737 REGISTER_LONG_CONSTANT("ARES_NI_DGRAM", ARES_NI_DGRAM, CONST_PERSISTENT|CONST_CS);
1738 #endif
1739 #ifdef ARES_NI_TCP
1740 REGISTER_LONG_CONSTANT("ARES_NI_TCP", ARES_NI_TCP, CONST_PERSISTENT|CONST_CS);
1741 #endif
1742 #ifdef ARES_NI_UDP
1743 REGISTER_LONG_CONSTANT("ARES_NI_UDP", ARES_NI_UDP, CONST_PERSISTENT|CONST_CS);
1744 #endif
1745 #ifdef ARES_NI_SCTP
1746 REGISTER_LONG_CONSTANT("ARES_NI_SCTP", ARES_NI_SCTP, CONST_PERSISTENT|CONST_CS);
1747 #endif
1748 #ifdef ARES_NI_DCCP
1749 REGISTER_LONG_CONSTANT("ARES_NI_DCCP", ARES_NI_DCCP, CONST_PERSISTENT|CONST_CS);
1750 #endif
1751 #ifdef ARES_NI_NUMERICSCOPE
1752 REGISTER_LONG_CONSTANT("ARES_NI_NUMERICSCOPE", ARES_NI_NUMERICSCOPE, CONST_PERSISTENT|CONST_CS);
1753 #endif
1754 #ifdef ARES_NI_LOOKUPHOST
1755 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPHOST", ARES_NI_LOOKUPHOST, CONST_PERSISTENT|CONST_CS);
1756 #endif
1757 #ifdef ARES_NI_LOOKUPSERVICE
1758 REGISTER_LONG_CONSTANT("ARES_NI_LOOKUPSERVICE", ARES_NI_LOOKUPSERVICE, CONST_PERSISTENT|CONST_CS);
1759 #endif
1760 #ifdef ARES_NI_IDN
1761 REGISTER_LONG_CONSTANT("ARES_NI_IDN", ARES_NI_IDN, CONST_PERSISTENT|CONST_CS);
1762 #endif
1763 #ifdef ARES_NI_IDN_ALLOW_UNASSIGNED
1764 REGISTER_LONG_CONSTANT("ARES_NI_IDN_ALLOW_UNASSIGNED", ARES_NI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
1765 #endif
1766 #ifdef ARES_NI_IDN_USE_STD
1767 REGISTER_LONG_CONSTANT("ARES_NI_IDN_USE_STD", ARES_NI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
1768 #endif
1769
1770 /*
1771 * Address Info constants
1772 */
1773 #ifdef ARES_AI_CANONNAME
1774 REGISTER_LONG_CONSTANT("ARES_AI_CANONNAME", ARES_AI_CANONNAME, CONST_PERSISTENT|CONST_CS);
1775 #endif
1776 #ifdef ARES_AI_NUMERICHOST
1777 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICHOST", ARES_AI_NUMERICHOST, CONST_PERSISTENT|CONST_CS);
1778 #endif
1779 #ifdef ARES_AI_PASSIVE
1780 REGISTER_LONG_CONSTANT("ARES_AI_PASSIVE", ARES_AI_PASSIVE, CONST_PERSISTENT|CONST_CS);
1781 #endif
1782 #ifdef ARES_AI_NUMERICSERV
1783 REGISTER_LONG_CONSTANT("ARES_AI_NUMERICSERV", ARES_AI_NUMERICSERV, CONST_PERSISTENT|CONST_CS);
1784 #endif
1785 #ifdef ARES_AI_V
1786 REGISTER_LONG_CONSTANT("ARES_AI_V", ARES_AI_V, CONST_PERSISTENT|CONST_CS);
1787 #endif
1788 #ifdef ARES_AI_ALL
1789 REGISTER_LONG_CONSTANT("ARES_AI_ALL", ARES_AI_ALL, CONST_PERSISTENT|CONST_CS);
1790 #endif
1791 #ifdef ARES_AI_ADDRCONFIG
1792 REGISTER_LONG_CONSTANT("ARES_AI_ADDRCONFIG", ARES_AI_ADDRCONFIG, CONST_PERSISTENT|CONST_CS);
1793 #endif
1794 #ifdef ARES_AI_IDN
1795 REGISTER_LONG_CONSTANT("ARES_AI_IDN", ARES_AI_IDN, CONST_PERSISTENT|CONST_CS);
1796 #endif
1797 #ifdef ARES_AI_IDN_ALLOW_UNASSIGNED
1798 REGISTER_LONG_CONSTANT("ARES_AI_IDN_ALLOW_UNASSIGNED", ARES_AI_IDN_ALLOW_UNASSIGNED, CONST_PERSISTENT|CONST_CS);
1799 #endif
1800 #ifdef ARES_AI_IDN_USE_STD
1801 REGISTER_LONG_CONSTANT("ARES_AI_IDN_USE_STD", ARES_AI_IDN_USE_STD, CONST_PERSISTENT|CONST_CS);
1802 #endif
1803 #ifdef ARES_AI_CANONIDN
1804 REGISTER_LONG_CONSTANT("ARES_AI_CANONIDN", ARES_AI_CANONIDN, CONST_PERSISTENT|CONST_CS);
1805 #endif
1806 #ifdef ARES_AI_MASK
1807 REGISTER_LONG_CONSTANT("ARES_AI_MASK", ARES_AI_MASK, CONST_PERSISTENT|CONST_CS);
1808 #endif
1809 #ifdef ARES_GETSOCK_MAXNUM
1810 REGISTER_LONG_CONSTANT("ARES_GETSOCK_MAXNUM", ARES_GETSOCK_MAXNUM, CONST_PERSISTENT|CONST_CS);
1811 #endif
1812
1813 /*
1814 * ns_t (type) constants (arpa/nameser.h)
1815 */
1816
1817 /* (1) Host address. */
1818 REGISTER_LONG_CONSTANT("ARES_T_A", T_A, CONST_CS|CONST_PERSISTENT);
1819 /* (2) Authoritative server. */
1820 REGISTER_LONG_CONSTANT("ARES_T_NS", T_NS, CONST_CS|CONST_PERSISTENT);
1821 /* (3) Mail destination. */
1822 REGISTER_LONG_CONSTANT("ARES_T_MD", T_MD, CONST_CS|CONST_PERSISTENT);
1823 /* (4) Mail forwarder. */
1824 REGISTER_LONG_CONSTANT("ARES_T_MF", T_MF, CONST_CS|CONST_PERSISTENT);
1825 /* (5) Canonical name. */
1826 REGISTER_LONG_CONSTANT("ARES_T_CNAME", T_CNAME, CONST_CS|CONST_PERSISTENT);
1827 /* (6) Start of authority zone. */
1828 REGISTER_LONG_CONSTANT("ARES_T_SOA", T_SOA, CONST_CS|CONST_PERSISTENT);
1829 /* (7) Mailbox domain name. */
1830 REGISTER_LONG_CONSTANT("ARES_T_MB", T_MB, CONST_CS|CONST_PERSISTENT);
1831 /* (8) Mail group member. */
1832 REGISTER_LONG_CONSTANT("ARES_T_MG", T_MG, CONST_CS|CONST_PERSISTENT);
1833 /* (9) Mail rename name. */
1834 REGISTER_LONG_CONSTANT("ARES_T_MR", T_MR, CONST_CS|CONST_PERSISTENT);
1835 /* (10) Null resource record. */
1836 REGISTER_LONG_CONSTANT("ARES_T_NULL", T_NULL, CONST_CS|CONST_PERSISTENT);
1837 /* (11) Well known service. */
1838 REGISTER_LONG_CONSTANT("ARES_T_WKS", T_WKS, CONST_CS|CONST_PERSISTENT);
1839 /* (12) Domain name pointer. */
1840 REGISTER_LONG_CONSTANT("ARES_T_PTR", T_PTR, CONST_CS|CONST_PERSISTENT);
1841 /* (13) Host information. */
1842 REGISTER_LONG_CONSTANT("ARES_T_HINFO", T_HINFO, CONST_CS|CONST_PERSISTENT);
1843 /* (14) Mailbox information. */
1844 REGISTER_LONG_CONSTANT("ARES_T_MINFO", T_MINFO, CONST_CS|CONST_PERSISTENT);
1845 /* (15) Mail routing information. */
1846 REGISTER_LONG_CONSTANT("ARES_T_MX", T_MX, CONST_CS|CONST_PERSISTENT);
1847 /* (16) Text strings. */
1848 REGISTER_LONG_CONSTANT("ARES_T_TXT", T_TXT, CONST_CS|CONST_PERSISTENT);
1849 /* (17) Responsible person. */
1850 REGISTER_LONG_CONSTANT("ARES_T_RP", T_RP, CONST_CS|CONST_PERSISTENT);
1851 /* (18) AFS cell database. */
1852 REGISTER_LONG_CONSTANT("ARES_T_AFSDB", T_AFSDB, CONST_CS|CONST_PERSISTENT);
1853 /* (19) X_25 calling address. */
1854 REGISTER_LONG_CONSTANT("ARES_T_X25", T_X25, CONST_CS|CONST_PERSISTENT);
1855 /* (20) ISDN calling address. */
1856 REGISTER_LONG_CONSTANT("ARES_T_ISDN", T_ISDN, CONST_CS|CONST_PERSISTENT);
1857 /* (21) Router. */
1858 REGISTER_LONG_CONSTANT("ARES_T_RT", T_RT, CONST_CS|CONST_PERSISTENT);
1859 /* (22) NSAP address. */
1860 REGISTER_LONG_CONSTANT("ARES_T_NSAP", T_NSAP, CONST_CS|CONST_PERSISTENT);
1861 /* (23) Reverse NSAP lookup (deprecated). */
1862 /* REGISTER_LONG_CONSTANT("ARES_T_NSAP_PTR", T_NSAP_PTR, CONST_CS|CONST_PERSISTENT); */
1863 /* (24) Security signature. */
1864 REGISTER_LONG_CONSTANT("ARES_T_SIG", T_SIG, CONST_CS|CONST_PERSISTENT);
1865 /* (25) Security key. */
1866 REGISTER_LONG_CONSTANT("ARES_T_KEY", T_KEY, CONST_CS|CONST_PERSISTENT);
1867 /* (26) X.400 mail mapping. */
1868 REGISTER_LONG_CONSTANT("ARES_T_PX", T_PX, CONST_CS|CONST_PERSISTENT);
1869 /* (27) Geographical position (withdrawn). */
1870 /* REGISTER_LONG_CONSTANT("ARES_T_GPOS", T_GPOS, CONST_CS|CONST_PERSISTENT); */
1871 /* (28) Ip6 Address. */
1872 REGISTER_LONG_CONSTANT("ARES_T_AAAA", T_AAAA, CONST_CS|CONST_PERSISTENT);
1873 /* (29) Location Information. */
1874 REGISTER_LONG_CONSTANT("ARES_T_LOC", T_LOC, CONST_CS|CONST_PERSISTENT);
1875 /* (30) Next domain (security). */
1876 REGISTER_LONG_CONSTANT("ARES_T_NXT", T_NXT, CONST_CS|CONST_PERSISTENT);
1877 /* (31) Endpoint identifier. */
1878 REGISTER_LONG_CONSTANT("ARES_T_EID", T_EID, CONST_CS|CONST_PERSISTENT);
1879 /* (32) Nimrod Locator. */
1880 REGISTER_LONG_CONSTANT("ARES_T_NIMLOC", T_NIMLOC, CONST_CS|CONST_PERSISTENT);
1881 /* (33) Server Selection. */
1882 REGISTER_LONG_CONSTANT("ARES_T_SRV", T_SRV, CONST_CS|CONST_PERSISTENT);
1883 /* (34) ATM Address */
1884 REGISTER_LONG_CONSTANT("ARES_T_ATMA", T_ATMA, CONST_CS|CONST_PERSISTENT);
1885 /* (35) Naming Authority PoinTeR */
1886 REGISTER_LONG_CONSTANT("ARES_T_NAPTR", T_NAPTR, CONST_CS|CONST_PERSISTENT);
1887 /* (36) Key Exchange */
1888 /* REGISTER_LONG_CONSTANT("ARES_T_KX", T_KX, CONST_CS|CONST_PERSISTENT); */
1889 /* (37) Certification record */
1890 /* REGISTER_LONG_CONSTANT("ARES_T_CERT", T_CERT, CONST_CS|CONST_PERSISTENT); */
1891 /* (38) IPv6 address (deprecates AAAA) */
1892 REGISTER_LONG_CONSTANT("ARES_T_A6", T_A6, CONST_CS|CONST_PERSISTENT);
1893 /* (39) Non-terminal DNAME (for IPv6) */
1894 REGISTER_LONG_CONSTANT("ARES_T_DNAME", T_DNAME, CONST_CS|CONST_PERSISTENT);
1895 /* (40) Kitchen sink (experimentatl) */
1896 /* REGISTER_LONG_CONSTANT("ARES_T_SINK", T_SINK, CONST_CS|CONST_PERSISTENT); */
1897 /* (41) EDNS0 option (meta-RR) */
1898 /* REGISTER_LONG_CONSTANT("ARES_T_OPT", T_OPT, CONST_CS|CONST_PERSISTENT); */
1899 /* (250) Transaction signature. */
1900 REGISTER_LONG_CONSTANT("ARES_T_TSIG", T_TSIG, CONST_CS|CONST_PERSISTENT);
1901 /* (251) Incremental zone transfer. */
1902 REGISTER_LONG_CONSTANT("ARES_T_IXFR", T_IXFR, CONST_CS|CONST_PERSISTENT);
1903 /* (252) Transfer zone of authority. */
1904 REGISTER_LONG_CONSTANT("ARES_T_AXFR", T_AXFR, CONST_CS|CONST_PERSISTENT);
1905 /* (253) Transfer mailbox records. */
1906 REGISTER_LONG_CONSTANT("ARES_T_MAILB", T_MAILB, CONST_CS|CONST_PERSISTENT);
1907 /* (254) Transfer mail agent records. */
1908 REGISTER_LONG_CONSTANT("ARES_T_MAILA", T_MAILA, CONST_CS|CONST_PERSISTENT);
1909 /* (255) Wildcard match. */
1910 REGISTER_LONG_CONSTANT("ARES_T_ANY", T_ANY, CONST_CS|CONST_PERSISTENT);
1911
1912 /*
1913 * ns_c (dnsclass) constants (arpa/nameser.h)
1914 */
1915
1916 /* (1) Internet. */
1917 REGISTER_LONG_CONSTANT("ARES_C_IN", C_IN, CONST_CS|CONST_PERSISTENT);
1918 /* (2) unallocated/unsupported. */
1919 /* REGISTER_LONG_CONSTANT("ARES_C_2", C_2, CONST_CS|CONST_PERSISTENT); */
1920 /* (3) MIT Chaos-net. */
1921 REGISTER_LONG_CONSTANT("ARES_C_CHAOS", C_CHAOS, CONST_CS|CONST_PERSISTENT);
1922 /* (4) MIT Hesiod. */
1923 REGISTER_LONG_CONSTANT("ARES_C_HS", C_HS, CONST_CS|CONST_PERSISTENT);
1924 /* (254) for prereq. sections in update requests */
1925 /* REGISTER_LONG_CONSTANT("ARES_C_NONE", C_NONE, CONST_CS|CONST_PERSISTENT); */
1926 /* (255) Wildcard match. */
1927 REGISTER_LONG_CONSTANT("ARES_C_ANY", C_ANY, CONST_CS|CONST_PERSISTENT);
1928
1929 le_ares = zend_register_list_destructors_ex(php_ares_le_dtor, NULL, PHP_ARES_LE_NAME, module_number);
1930 le_ares_query = zend_register_list_destructors_ex(php_ares_query_le_dtor, NULL, PHP_ARES_QUERY_LE_NAME, module_number);
1931
1932 return SUCCESS;
1933 }
1934 /* }}} */
1935
1936 /* {{{ PHP_MSHUTDOWN_FUNCTION */
1937 static PHP_MSHUTDOWN_FUNCTION(ares)
1938 {
1939 #ifdef HAVE_ARES_LIBRARY_CLEANUP
1940 ares_library_cleanup();
1941 #endif
1942 return SUCCESS;
1943 }
1944 /* }}} */
1945
1946 /* {{{ PHP_MINFO_FUNCTION */
1947 static PHP_MINFO_FUNCTION(ares)
1948 {
1949 php_info_print_table_start();
1950 php_info_print_table_header(2, "AsyncResolver support", "enabled");
1951 php_info_print_table_row(2, "Version", PHP_ARES_VERSION);
1952 php_info_print_table_end();
1953
1954 php_info_print_table_start();
1955 php_info_print_table_header(3, "Used Library", "compiled", "linked");
1956 php_info_print_table_row(3,
1957 PHP_ARES_LIBNAME,
1958 #ifdef ARES_VERSION_STR
1959 ARES_VERSION_STR,
1960 #else
1961 "unkown",
1962 #endif
1963 #ifdef HAVE_ARES_VERSION
1964 ares_version(NULL)
1965 #else
1966 "unkown"
1967 #endif
1968 );
1969 php_info_print_table_end();
1970 }
1971 /* }}} */
1972
1973 #ifdef ZEND_ENGINE_2
1974 ZEND_BEGIN_ARG_INFO(ai_ares_select, 0)
1975 ZEND_ARG_PASS_INFO(1)
1976 ZEND_ARG_PASS_INFO(1)
1977 ZEND_ARG_PASS_INFO(0)
1978 ZEND_END_ARG_INFO();
1979
1980 ZEND_BEGIN_ARG_INFO(ai_ares_result, 0)
1981 ZEND_ARG_PASS_INFO(0)
1982 ZEND_ARG_PASS_INFO(1)
1983 ZEND_ARG_PASS_INFO(1)
1984 ZEND_END_ARG_INFO();
1985
1986 ZEND_BEGIN_ARG_INFO(ai_ares_fds, 0)
1987 ZEND_ARG_PASS_INFO(0)
1988 ZEND_ARG_PASS_INFO(1)
1989 ZEND_ARG_PASS_INFO(1)
1990 ZEND_END_ARG_INFO();
1991 #else
1992 static unsigned char ai_ares_select[] = {3, BYREF_FORCE, BYREF_FORCE, BYREF_NONE};
1993 static unsigned char ai_ares_result[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
1994 static unsigned char ai_ares_fds[] = {4, BYREF_NONE, BYREF_FORCE, BYREF_FORCE};
1995 #endif
1996
1997 /* {{{ ares_functions[] */
1998 zend_function_entry ares_functions[] = {
1999 #ifdef HAVE_ARES_VERSION
2000 PHP_FE(ares_version, NULL)
2001 #endif
2002 PHP_FE(ares_init, NULL)
2003 PHP_FE(ares_destroy, NULL)
2004 PHP_FE(ares_strerror, NULL)
2005 #ifdef HAVE_ARES_CANCEL
2006 PHP_FE(ares_cancel, NULL)
2007 #endif
2008 PHP_FE(ares_search, NULL)
2009 PHP_FE(ares_query, NULL)
2010 PHP_FE(ares_send, NULL)
2011 PHP_FE(ares_mkquery, NULL)
2012 PHP_FE(ares_gethostbyname, NULL)
2013 PHP_FE(ares_gethostbyaddr, NULL)
2014 #ifdef HAVE_ARES_GETNAMEINFO
2015 PHP_FE(ares_getnameinfo, NULL)
2016 #endif
2017 PHP_FE(ares_result, ai_ares_result)
2018 PHP_FE(ares_packet, NULL)
2019 PHP_FE(ares_process_all, NULL)
2020 PHP_FE(ares_process_once, NULL)
2021 PHP_FE(ares_process, NULL)
2022 PHP_FE(ares_select, ai_ares_select)
2023 PHP_FE(ares_fds, ai_ares_fds)
2024 PHP_FE(ares_timeout, NULL)
2025 {NULL, NULL, NULL}
2026 };
2027 /* }}} */
2028
2029 /* {{{ ares_module_entry */
2030 zend_module_entry ares_module_entry = {
2031 STANDARD_MODULE_HEADER,
2032 "ares",
2033 ares_functions,
2034 PHP_MINIT(ares),
2035 PHP_MSHUTDOWN(ares),
2036 NULL,
2037 NULL,
2038 PHP_MINFO(ares),
2039 PHP_ARES_VERSION,
2040 STANDARD_MODULE_PROPERTIES
2041 };
2042 /* }}} */
2043
2044 #ifdef COMPILE_DL_ARES
2045 ZEND_GET_MODULE(ares)
2046 #endif
2047
2048 /*
2049 * Local variables:
2050 * tab-width: 4
2051 * c-basic-offset: 4
2052 * End:
2053 * vim600: noet sw=4 ts=4 fdm=marker
2054 * vim<600: noet sw=4 ts=4
2055 */