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