Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polyfill dns_check_record(), dns_get_record(), and dns_get_mx() #1067

Merged
merged 15 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"array": "c",
"string": "c",
"string_view": "c",
"vector": "c"
"vector": "c",
"unistd.h": "c",
"zend_api.h": "c"
},
"autoImportFileExcludePatterns": [
"@wp-playground/client"
Expand Down
1 change: 1 addition & 0 deletions packages/php-wasm/compile/php/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ RUN cp -v /root/php-src/.libs/libphp*.la /root/lib/libphp.la
RUN cp -v /root/php-src/.libs/libphp*.a /root/lib/libphp.a

COPY ./php/php_wasm.c /root/
COPY ./php/dns_polyfill.c /root/
COPY ./php/proc_open* /root/

RUN if [[ "${PHP_VERSION:0:1}" -le "7" && "${PHP_VERSION:2:1}" -le "3" ]]; then \
Expand Down
253 changes: 253 additions & 0 deletions packages/php-wasm/compile/php/dns_polyfill.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
/* {{{ includes */
#include "php.h"
#include "php_network.h"
#include "zend_API.h"

#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#include <netinet/in.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <netdb.h>
#ifdef _OSD_POSIX
#undef STATUS
#undef T_UNSPEC
#endif
#ifdef HAVE_ARPA_NAMESER_H
#ifdef DARWIN
# define BIND_8_COMPAT 1
#endif
#include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
#include <resolv.h>
#if defined(__HAIKU__)
extern void __res_ndestroy(res_state statp);
#define res_ndestroy __res_ndestroy
#endif
#endif
#ifdef HAVE_DNS_H
#include <dns.h>
#endif

#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 255
#endif

/* For the local hostname obtained via gethostname which is different from the
dns-related MAXHOSTNAMELEN constant above */
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif

/* type compat */
#ifndef DNS_T_A
#define DNS_T_A 1
#endif
#ifndef DNS_T_NS
#define DNS_T_NS 2
#endif
#ifndef DNS_T_CNAME
#define DNS_T_CNAME 5
#endif
#ifndef DNS_T_SOA
#define DNS_T_SOA 6
#endif
#ifndef DNS_T_PTR
#define DNS_T_PTR 12
#endif
#ifndef DNS_T_HINFO
#define DNS_T_HINFO 13
#endif
#ifndef DNS_T_MINFO
#define DNS_T_MINFO 14
#endif
#ifndef DNS_T_MX
#define DNS_T_MX 15
#endif
#ifndef DNS_T_TXT
#define DNS_T_TXT 16
#endif
#ifndef DNS_T_AAAA
#define DNS_T_AAAA 28
#endif
#ifndef DNS_T_SRV
#define DNS_T_SRV 33
#endif
#ifndef DNS_T_NAPTR
#define DNS_T_NAPTR 35
#endif
#ifndef DNS_T_A6
#define DNS_T_A6 38
#endif
#ifndef DNS_T_CAA
#define DNS_T_CAA 257
#endif

#ifndef DNS_T_ANY
#define DNS_T_ANY 255
#endif
/* }}} */

#ifndef HFIXEDSZ
#define HFIXEDSZ 12 /* fixed data in header <arpa/nameser.h> */
#endif /* HFIXEDSZ */

#ifndef QFIXEDSZ
#define QFIXEDSZ 4 /* fixed data in query <arpa/nameser.h> */
#endif /* QFIXEDSZ */

#undef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 1024

#ifndef MAXRESOURCERECORDS
#define MAXRESOURCERECORDS 64
#endif /* MAXRESOURCERECORDS */

#define PHP_DNS_A 0x00000001
#define PHP_DNS_NS 0x00000002
#define PHP_DNS_CNAME 0x00000010
#define PHP_DNS_SOA 0x00000020
#define PHP_DNS_PTR 0x00000800
#define PHP_DNS_HINFO 0x00001000
#if !defined(PHP_WIN32)
# define PHP_DNS_CAA 0x00002000
#endif
#define PHP_DNS_MX 0x00004000
#define PHP_DNS_TXT 0x00008000
#define PHP_DNS_A6 0x01000000
#define PHP_DNS_SRV 0x02000000
#define PHP_DNS_NAPTR 0x04000000
#define PHP_DNS_AAAA 0x08000000
#define PHP_DNS_ANY 0x10000000
#define PHP_DNS_NUM_TYPES 13 /* Number of DNS Types Supported by PHP currently */
#define PHP_DNS_ALL (PHP_DNS_A|PHP_DNS_NS|PHP_DNS_CNAME|PHP_DNS_SOA|PHP_DNS_PTR|PHP_DNS_HINFO|PHP_DNS_CAA|PHP_DNS_MX|PHP_DNS_TXT|PHP_DNS_A6|PHP_DNS_SRV|PHP_DNS_NAPTR|PHP_DNS_AAAA)

typedef union {
HEADER qb1;
uint8_t qb2[65536];
} querybuf;

ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_check_record, 0, 0, 1)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, type)
ZEND_END_ARG_INFO()

PHP_FUNCTION(dns_check_record)
{
HEADER *hp;
querybuf answer = {0};
char *hostname;
size_t hostname_len;
size_t rectype_len = 0;
zend_string *rectype = NULL;
int type = DNS_T_MX, i;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &hostname, &hostname_len, &rectype, &rectype_len) == FAILURE) {
return;
}

if (hostname_len == 0) {
php_error_docref(NULL, E_WARNING, "Host cannot be empty");
RETURN_FALSE;
}

RETURN_FALSE;
}

/* {{{ Get any Resource Record corresponding to a given Internet host name */
ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_record, 0, 0, 1)
ZEND_ARG_INFO(0, hostname)
ZEND_ARG_INFO(0, type)
ZEND_ARG_ARRAY_INFO(1, authns, 1)
ZEND_ARG_ARRAY_INFO(1, addtl, 1)
ZEND_ARG_INFO(0, raw)
ZEND_END_ARG_INFO()


PHP_FUNCTION(dns_get_record)
{
char *hostname;
size_t hostname_len;
zend_long type_param = PHP_DNS_ANY;
zval *authns = NULL, *addtl = NULL;
int type_to_fetch;
int dns_errno;
HEADER *hp;
querybuf answer = {0};
uint8_t *cp = NULL, *end = NULL;
int n, qd, an, ns = 0, ar = 0;
int type, first_query = 1, store_results = 1;
zend_bool raw = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lz!z!b",
&hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
return;
}

if (authns) {
array_init(authns);
if (!authns) {
RETURN_FALSE;
}
}
if (addtl) {
array_init(addtl);
if (!addtl) {
RETURN_FALSE;
}
}

/* Initialize the return array */
array_init(return_value);
}

/* }}} */

/* {{{ Get MX records corresponding to a given Internet host name */
ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_mx, 0, 0, 2)
ZEND_ARG_INFO(0, hostname)
ZEND_ARG_INFO(1, mxhosts) /* ARRAY_INFO(1, mxhosts, 1) */
ZEND_ARG_INFO(1, weight) /* ARRAY_INFO(1, weight, 1) */
ZEND_END_ARG_INFO()

#define arginfo_getmxrr arginfo_dns_get_mx

PHP_FUNCTION(dns_get_mx)
{
char *hostname;
size_t hostname_len;
zval *mx_list, *weight_list = NULL;
int count, qdc;
u_short type, weight;
querybuf answer = {0};
char buf[MAXHOSTNAMELEN] = {0};
HEADER *hp;
uint8_t *cp, *end;
int i;

ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_STRING(hostname, hostname_len)
Z_PARAM_ZVAL(mx_list)
Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(weight_list)
ZEND_PARSE_PARAMETERS_END();

array_init(mx_list);
if (!mx_list) {
RETURN_FALSE;
}

if (weight_list) {
array_init(weight_list);
if (!weight_list) {
RETURN_FALSE;
}
}

RETURN_FALSE;
}
/* }}} */
42 changes: 38 additions & 4 deletions packages/php-wasm/compile/php/php_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
#include "zend_globals_macros.h"
#include "zend_exceptions.h"
#include "zend_closures.h"
#include "zend_constants.h"
#include "zend_hash.h"
#include "rfc1867.h"
#include "SAPI.h"
#include "proc_open.h"
#include "dns_polyfill.c"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#includeing a *.c file seems a bit unorthodox. Doesn't this leave us open to having issues with double definitions down the track?

I feel it would be more typical to ensure dns_polyfill.c gets compiled separately and then linked into the final output? i.e. including it in the build command here:

We'd need another header file to declare the functions so they can be included in the additional_functions array. But still, that seems a bit more conventional.

But I might be missing something. Was there a reason why this needed to be included as a C file? Could the DNS functions simply be added to the giant php_wasm.c file?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bgrgicak I gave this a try on a branch of my own and it seems to be working: p-jackson@e331922

I'm not familiar with all of PHP's C macros, but chatgpt said the same PHP_FUNCTION macro can be used for declaring functions too. I also had to move the arginfo declarations into the header file since that's important info that needs to be part of the ccall to register the functions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Thank you for working on it. I will add these changes to the PR later today and if everything works we can merge it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the header file in a51fe85.
Thank you for helping me!


unsigned int wasm_sleep(unsigned int time)
{
Expand Down Expand Up @@ -379,6 +381,8 @@ ZEND_BEGIN_ARG_INFO(arginfo_dl, 0)
ZEND_ARG_INFO(0, extension_filename)
ZEND_END_ARG_INFO()



/* Enable PHP to exchange messages with JavaScript */
PHP_FUNCTION(post_message_to_js)
{
Expand Down Expand Up @@ -437,9 +441,14 @@ EMSCRIPTEN_KEEPALIVE int wasm_select(int max_fd, fd_set *read_fds, fd_set *write

static const zend_function_entry additional_functions[] = {
ZEND_FE(dl, arginfo_dl)
PHP_FE(cli_set_process_title, arginfo_cli_set_process_title)
PHP_FE(cli_get_process_title, arginfo_cli_get_process_title)
PHP_FE(post_message_to_js, arginfo_post_message_to_js){NULL, NULL, NULL}};
ZEND_FE(dns_get_mx, arginfo_dns_get_mx)
ZEND_FALIAS(getmxrr, dns_get_mx, arginfo_getmxrr)
adamziel marked this conversation as resolved.
Show resolved Hide resolved
ZEND_FE(dns_check_record, arginfo_dns_check_record)
adamziel marked this conversation as resolved.
Show resolved Hide resolved
ZEND_FE(dns_get_record, arginfo_dns_get_record)
PHP_FE(cli_set_process_title, arginfo_cli_set_process_title)
PHP_FE(cli_get_process_title, arginfo_cli_get_process_title)
PHP_FE(post_message_to_js, arginfo_post_message_to_js){NULL, NULL, NULL}
};

typedef struct wasm_cli_arg
{
Expand Down Expand Up @@ -483,7 +492,12 @@ int run_cli()
#else
static const zend_function_entry additional_functions[] = {
ZEND_FE(dl, arginfo_dl)
PHP_FE(post_message_to_js, arginfo_post_message_to_js){NULL, NULL, NULL}};
ZEND_FE(dns_get_mx, arginfo_dns_get_mx)
ZEND_FALIAS(getmxrr, dns_get_mx, arginfo_getmxrr)
ZEND_FE(dns_check_record, arginfo_dns_check_record)
ZEND_FE(dns_get_record, arginfo_dns_get_record)
PHP_FE(post_message_to_js, arginfo_post_message_to_js){NULL, NULL, NULL}
};
#endif

#if !defined(TSRMLS_DC)
Expand Down Expand Up @@ -1160,6 +1174,26 @@ int wasm_sapi_request_init()

php_register_variable("PHP_SELF", "-", NULL TSRMLS_CC);

// PHP expects the module_number to be defined before
// REGISTER_LONG_CONSTANT is called. 0 stands for the
// core module.
int module_number = 0;
REGISTER_LONG_CONSTANT("DNS_A", PHP_DNS_A, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_NS", PHP_DNS_NS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_CNAME", PHP_DNS_CNAME, CONST_CS | CONST_PERSISTENT);
adamziel marked this conversation as resolved.
Show resolved Hide resolved
REGISTER_LONG_CONSTANT("DNS_SOA", PHP_DNS_SOA, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_PTR", PHP_DNS_PTR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_HINFO", PHP_DNS_HINFO, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_CAA", PHP_DNS_CAA, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_MX", PHP_DNS_MX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_TXT", PHP_DNS_TXT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_SRV", PHP_DNS_SRV, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_NAPTR", PHP_DNS_NAPTR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_AAAA", PHP_DNS_AAAA, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_A6", PHP_DNS_A6, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_ANY", PHP_DNS_ANY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DNS_ALL", PHP_DNS_ALL, CONST_CS | CONST_PERSISTENT);

return SUCCESS;
}

Expand Down
Loading
Loading