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