Exposing the sin6_scope_id parameter in socket_recvfrom, socket_sendto and socket_connect for IPv6 link-local unicast/multicast communications. #220

Closed
wants to merge 3 commits into
from
View
@@ -193,6 +193,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_connect, 0, 0, 2)
ZEND_ARG_INFO(0, socket)
ZEND_ARG_INFO(0, addr)
ZEND_ARG_INFO(0, port)
+ ZEND_ARG_INFO(0, ifindex)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_strerror, 0, 0, 1)
@@ -226,6 +227,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_recvfrom, 0, 0, 5)
ZEND_ARG_INFO(0, flags)
ZEND_ARG_INFO(1, name)
ZEND_ARG_INFO(1, port)
+ ZEND_ARG_INFO(1, ifindex)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendto, 0, 0, 5)
@@ -235,6 +237,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_sendto, 0, 0, 5)
ZEND_ARG_INFO(0, flags)
ZEND_ARG_INFO(0, addr)
ZEND_ARG_INFO(0, port)
+ ZEND_ARG_INFO(0, ifindex)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_get_option, 0, 0, 3)
@@ -1486,18 +1489,18 @@ PHP_FUNCTION(socket_create)
}
/* }}} */
-/* {{{ proto bool socket_connect(resource socket, string addr [, int port])
+/* {{{ proto bool socket_connect(resource socket, string addr [, int port [, int ifindex]])
Opens a connection to addr:port on the socket specified by socket */
PHP_FUNCTION(socket_connect)
{
zval *arg1;
php_socket *php_sock;
char *addr;
int retval, addr_len;
- long port = 0;
+ long port = 0, ifindex = -1;
int argc = ZEND_NUM_ARGS();
- if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "rs|ll", &arg1, &addr, &addr_len, &port, &ifindex) == FAILURE) {
return;
}
@@ -1508,7 +1511,7 @@ PHP_FUNCTION(socket_connect)
case AF_INET6: {
struct sockaddr_in6 sin6 = {0};
- if (argc != 3) {
+ if (argc != 3 && argc != 4) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Socket of type AF_INET6 requires 3 arguments");
RETURN_FALSE;
}
@@ -1518,6 +1521,8 @@ PHP_FUNCTION(socket_connect)
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons((unsigned short int)port);
+ if(ifindex != -1) sin6.sin6_scope_id = ifindex;
+
if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) {
RETURN_FALSE;
}
@@ -1742,11 +1747,11 @@ PHP_FUNCTION(socket_send)
}
/* }}} */
-/* {{{ proto int socket_recvfrom(resource socket, string &buf, int len, int flags, string &name [, int &port])
+/* {{{ proto int socket_recvfrom(resource socket, string &buf, int len, int flags, string &name [, int &port [, int &ifindex]])
Receives data from a socket, connected or not */
PHP_FUNCTION(socket_recvfrom)
{
- zval *arg1, *arg2, *arg5, *arg6 = NULL;
+ zval *arg1, *arg2, *arg5, *arg6 = NULL, *arg7 = NULL;
php_socket *php_sock;
struct sockaddr_un s_un;
struct sockaddr_in sin;
@@ -1759,7 +1764,7 @@ PHP_FUNCTION(socket_recvfrom)
long arg3, arg4;
char *recv_buf, *address;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzllz|z", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzllz|zz", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7) == FAILURE) {
return;
}
@@ -1819,6 +1824,11 @@ PHP_FUNCTION(socket_recvfrom)
ZVAL_STRINGL(arg2, recv_buf, retval, 0);
ZVAL_STRING(arg5, address ? address : "0.0.0.0", 1);
ZVAL_LONG(arg6, ntohs(sin.sin_port));
+
+ if(arg7 != NULL) {
+ zval_dtor(arg7);
+ ZVAL_LONG(arg7, -1);
+ }
break;
#if HAVE_IPV6
case AF_INET6:
@@ -1849,6 +1859,10 @@ PHP_FUNCTION(socket_recvfrom)
ZVAL_STRINGL(arg2, recv_buf, retval, 0);
ZVAL_STRING(arg5, addr6[0] ? addr6 : "::", 1);
ZVAL_LONG(arg6, ntohs(sin6.sin6_port));
+ if(arg7 != NULL) {
+ zval_dtor(arg7);
+ ZVAL_LONG(arg7, sin6.sin6_scope_id);
+ }
break;
#endif
default:
@@ -1860,7 +1874,7 @@ PHP_FUNCTION(socket_recvfrom)
}
/* }}} */
-/* {{{ proto int socket_sendto(resource socket, string buf, int len, int flags, string addr [, int port])
+/* {{{ proto int socket_sendto(resource socket, string buf, int len, int flags, string addr [, int port [, int ifindex]])
Sends a message to a socket, whether it is connected or not */
PHP_FUNCTION(socket_sendto)
{
@@ -1872,11 +1886,11 @@ PHP_FUNCTION(socket_sendto)
struct sockaddr_in6 sin6;
#endif
int retval, buf_len, addr_len;
- long len, flags, port = 0;
+ long len, flags, port = 0, ifindex=-1;
char *buf, *addr;
int argc = ZEND_NUM_ARGS();
- if (zend_parse_parameters(argc TSRMLS_CC, "rslls|l", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) {
+ if (zend_parse_parameters(argc TSRMLS_CC, "rslls|ll", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port, &ifindex) == FAILURE) {
return;
}
@@ -1908,14 +1922,18 @@ PHP_FUNCTION(socket_sendto)
break;
#if HAVE_IPV6
case AF_INET6:
- if (argc != 6) {
+ if (argc != 6 && argc != 7) {
WRONG_PARAM_COUNT;
}
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons((unsigned short) port);
+ if(ifindex>-1) {
+ sin6.sin6_scope_id = ifindex;
+ }
+
if (! php_set_inet6_addr(&sin6, addr, php_sock TSRMLS_CC)) {
RETURN_FALSE;
}