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