@@ -77,6 +77,7 @@ struct key_value {
77
77
#define KEY_FILL_SOCKADDR "fill_sockaddr"
78
78
#define KEY_RECVMSG_RET "recvmsg_ret"
79
79
#define KEY_CMSG_LEN "cmsg_len"
80
+ static const struct key_value empty_key_value_list [] = {{0 }};
80
81
81
82
82
83
typedef void (from_zval_write_field )(const zval * arr_value , char * field , ser_context * ctx );
@@ -222,6 +223,12 @@ static void err_msg_dispose(struct err_s *err TSRMLS_DC)
222
223
}
223
224
}
224
225
}
226
+ static void allocations_dispose (zend_llist * * allocations )
227
+ {
228
+ zend_llist_destroy (* allocations );
229
+ efree (* allocations );
230
+ * allocations = NULL ;
231
+ }
225
232
226
233
static unsigned from_array_iterate (const zval * arr ,
227
234
void (* func )(zval * * elem , unsigned i , void * * args , ser_context * ctx ),
@@ -1660,8 +1667,7 @@ PHP_FUNCTION(socket_recvmsg)
1660
1667
1661
1668
/* we don;t need msghdr anymore; free it */
1662
1669
msghdr = NULL ;
1663
- zend_llist_destroy (allocations );
1664
- efree (allocations );
1670
+ allocations_dispose (& allocations );
1665
1671
1666
1672
zval_dtor (zmsg );
1667
1673
if (!err .has_error ) {
@@ -1723,6 +1729,86 @@ PHP_FUNCTION(socket_cmsg_space)
1723
1729
RETURN_LONG ((long )CMSG_SPACE (entry -> size + n * entry -> var_el_size ));
1724
1730
}
1725
1731
1732
+ int php_do_setsockopt_ipv6_rfc3542 (php_socket * php_sock , int level , int optname , zval * * arg4 )
1733
+ {
1734
+ struct err_s err = {0 };
1735
+ zend_llist * allocations = NULL ;
1736
+ void * opt_ptr ;
1737
+ socklen_t optlen ;
1738
+ int retval ;
1739
+
1740
+ assert (level == IPPROTO_IPV6 );
1741
+
1742
+ switch (optname ) {
1743
+ #ifdef IPV6_PKTINFO
1744
+ case IPV6_PKTINFO :
1745
+ opt_ptr = from_zval_run_conversions (* arg4 , php_sock , from_zval_write_in6_pktinfo ,
1746
+ sizeof (struct in6_pktinfo ), "in6_pktinfo" , & allocations , & err );
1747
+ if (err .has_error ) {
1748
+ err_msg_dispose (& err TSRMLS_CC );
1749
+ return FAILURE ;
1750
+ }
1751
+
1752
+ optlen = sizeof (struct in6_pktinfo );
1753
+ goto dosockopt ;
1754
+ #endif
1755
+ }
1756
+
1757
+ /* we also support IPV6_TCLASS, but that can be handled by the default
1758
+ * integer optval handling in the caller */
1759
+ return 1 ;
1760
+
1761
+ dosockopt :
1762
+ retval = setsockopt (php_sock -> bsd_socket , level , optname , opt_ptr , optlen );
1763
+ if (retval != 0 ) {
1764
+ PHP_SOCKET_ERROR (php_sock , "unable to set socket option" , errno );
1765
+ }
1766
+ allocations_dispose (& allocations );
1767
+
1768
+ return retval != 0 ? FAILURE : SUCCESS ;
1769
+ }
1770
+
1771
+ int php_do_getsockopt_ipv6_rfc3542 (php_socket * php_sock , int level , int optname , zval * result )
1772
+ {
1773
+ struct err_s err = {0 };
1774
+ void * buffer ;
1775
+ socklen_t size ;
1776
+ int res ;
1777
+ to_zval_read_field * reader ;
1778
+
1779
+ assert (level == IPPROTO_IPV6 );
1780
+
1781
+ switch (optname ) {
1782
+ #ifdef IPV6_PKTINFO
1783
+ case IPV6_PKTINFO :
1784
+ size = sizeof (struct in6_pktinfo );
1785
+ reader = & to_zval_read_in6_pktinfo ;
1786
+ break ;
1787
+ #endif
1788
+ default :
1789
+ return 1 ;
1790
+ }
1791
+
1792
+ buffer = ecalloc (1 , size );
1793
+ res = getsockopt (php_sock -> bsd_socket , level , optname , buffer , & size );
1794
+ if (res != 0 ) {
1795
+ PHP_SOCKET_ERROR (php_sock , "unable to get socket option" , errno );
1796
+ } else {
1797
+ zval * zv = to_zval_run_conversions (buffer , reader , "in6_pktinfo" ,
1798
+ empty_key_value_list , & err );
1799
+ if (err .has_error ) {
1800
+ err_msg_dispose (& err );
1801
+ res = -1 ;
1802
+ } else {
1803
+ ZVAL_COPY_VALUE (result , zv );
1804
+ efree (zv );
1805
+ }
1806
+ }
1807
+ efree (buffer );
1808
+
1809
+ return res == 0 ? SUCCESS : FAILURE ;
1810
+ }
1811
+
1726
1812
void php_socket_sendrecvmsg_init (INIT_FUNC_ARGS )
1727
1813
{
1728
1814
/* IPv6 ancillary data
0 commit comments