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