41
41
# include <netdb.h>
42
42
# include <netinet/in.h>
43
43
# include <netinet/tcp.h>
44
+ # include <netinet/udp.h>
44
45
# include <sys/un.h>
45
46
# include <arpa/inet.h>
46
47
# include <sys/time.h>
54
55
# ifdef HAVE_IF_NAMETOINDEX
55
56
# include <net/if.h>
56
57
# endif
58
+ # ifdef HAVE_NETINET_ETHER_H
59
+ # include <netinet/ether.h>
60
+ # include <netinet/ip.h>
61
+ # endif
57
62
# if defined(HAVE_LINUX_SOCK_DIAG_H )
58
63
# include <linux/sock_diag.h>
59
64
# else
@@ -120,6 +125,9 @@ static PHP_RSHUTDOWN_FUNCTION(sockets);
120
125
121
126
zend_class_entry * socket_ce ;
122
127
static zend_object_handlers socket_object_handlers ;
128
+ #ifdef AF_PACKET
129
+ zend_class_entry * socket_ethinfo_ce ;
130
+ #endif
123
131
124
132
static zend_object * socket_create_object (zend_class_entry * class_type ) {
125
133
php_socket * intern = zend_object_alloc (sizeof (php_socket ), class_type );
@@ -482,6 +490,9 @@ static PHP_MINIT_FUNCTION(sockets)
482
490
socket_object_handlers .get_gc = socket_get_gc ;
483
491
socket_object_handlers .compare = zend_objects_not_comparable ;
484
492
493
+ #if defined(AF_PACKET )
494
+ socket_ethinfo_ce = register_class_SocketEthernetInfo ();
495
+ #endif
485
496
address_info_ce = register_class_AddressInfo ();
486
497
address_info_ce -> create_object = address_info_create_object ;
487
498
address_info_ce -> default_object_handlers = & address_info_object_handlers ;
@@ -1505,7 +1516,7 @@ PHP_FUNCTION(socket_recvfrom)
1505
1516
struct sockaddr_in6 sin6 ;
1506
1517
#endif
1507
1518
#ifdef AF_PACKET
1508
- // struct sockaddr_ll sll;
1519
+ struct sockaddr_ll sll ;
1509
1520
#endif
1510
1521
char addrbuf [INET6_ADDRSTRLEN ];
1511
1522
socklen_t slen ;
@@ -1534,6 +1545,12 @@ PHP_FUNCTION(socket_recvfrom)
1534
1545
RETURN_FALSE ;
1535
1546
}
1536
1547
1548
+ #ifdef AF_PACKET
1549
+ if (php_sock -> type == AF_PACKET && arg3 < 2048 ) {
1550
+ RETURN_FALSE ;
1551
+ }
1552
+ #endif
1553
+
1537
1554
recv_buf = zend_string_alloc (arg3 + 1 , 0 );
1538
1555
1539
1556
switch (php_sock -> type ) {
@@ -1612,14 +1629,14 @@ PHP_FUNCTION(socket_recvfrom)
1612
1629
break ;
1613
1630
#endif
1614
1631
#ifdef AF_PACKET
1615
- /*
1616
1632
case AF_PACKET :
1617
1633
// TODO expose and use proper ethernet frame type instead i.e. src mac, dst mac and payload to userland
1618
1634
// ditto for socket_sendto
1619
1635
slen = sizeof (sll );
1620
1636
memset (& sll , 0 , sizeof (sll ));
1621
1637
sll .sll_family = AF_PACKET ;
1622
1638
char ifrname [IFNAMSIZ ];
1639
+ zval zpayload ;
1623
1640
1624
1641
retval = recvfrom (php_sock -> bsd_socket , ZSTR_VAL (recv_buf ), arg3 , arg4 , (struct sockaddr * )& sll , (socklen_t * )& slen );
1625
1642
@@ -1628,20 +1645,61 @@ PHP_FUNCTION(socket_recvfrom)
1628
1645
zend_string_efree (recv_buf );
1629
1646
RETURN_FALSE ;
1630
1647
}
1631
- ZSTR_LEN(recv_buf) = retval;
1632
- ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
1633
1648
1634
1649
if (UNEXPECTED (!if_indextoname (sll .sll_ifindex , ifrname ))) {
1635
1650
PHP_SOCKET_ERROR (php_sock , "unable to get the interface name" , errno );
1636
1651
zend_string_efree (recv_buf );
1637
1652
RETURN_FALSE ;
1638
1653
}
1639
1654
1640
- ZEND_TRY_ASSIGN_REF_NEW_STR(arg2, recv_buf);
1655
+ struct ethhdr * e = (struct ethhdr * )ZSTR_VAL (recv_buf );
1656
+ unsigned short protocol = ntohs (e -> h_proto );
1657
+ unsigned char * payload = ((unsigned char * )e + sizeof (struct ethhdr ));
1658
+
1659
+ object_init_ex (arg2 , socket_ethinfo_ce );
1660
+ zend_update_property_string (Z_OBJCE_P (arg2 ), Z_OBJ_P (arg2 ), ZEND_STRL ("macsrc" ), ether_ntoa ((struct ether_addr * )e -> h_source ));
1661
+ zend_update_property_string (Z_OBJCE_P (arg2 ), Z_OBJ_P (arg2 ), ZEND_STRL ("macdst" ), ether_ntoa ((struct ether_addr * )e -> h_dest ));
1662
+ array_init (& zpayload );
1663
+
1664
+ switch (protocol ) {
1665
+ case ETH_P_IP : {
1666
+ struct iphdr * ip = (struct iphdr * )payload ;
1667
+ unsigned char * ipdata = payload + (ip -> ihl * 4 );
1668
+ struct in_addr s , d ;
1669
+ s .s_addr = ip -> saddr ;
1670
+ d .s_addr = ip -> daddr ;
1671
+ add_assoc_string (& zpayload , "ipsrc" , inet_ntoa (s ));
1672
+ add_assoc_string (& zpayload , "ipdst" , inet_ntoa (d ));
1673
+
1674
+ switch (ip -> protocol ) {
1675
+ case IPPROTO_TCP : {
1676
+ struct tcphdr * tcp = (struct tcphdr * )ipdata ;
1677
+ add_assoc_long (& zpayload , "portsrc" , ntohs (tcp -> th_sport ));
1678
+ add_assoc_long (& zpayload , "portdst" , ntohs (tcp -> th_dport ));
1679
+ break ;
1680
+ }
1681
+ case IPPROTO_UDP : {
1682
+ struct udphdr * udp = (struct udphdr * )ipdata ;
1683
+ add_assoc_long (& zpayload , "portsrc" , ntohs (udp -> uh_sport ));
1684
+ add_assoc_long (& zpayload , "portdst" , ntohs (udp -> uh_dport ));
1685
+ break ;
1686
+ }
1687
+ default :
1688
+ zend_value_error ("unsupported ip header protocol" );
1689
+ RETURN_THROWS ();
1690
+ }
1691
+ break ;
1692
+ }
1693
+ default :
1694
+ zend_value_error ("unsupported ethernet protocol" );
1695
+ RETURN_THROWS ();
1696
+ }
1697
+
1698
+ zend_update_property (Z_OBJCE_P (arg2 ), Z_OBJ_P (arg2 ), ZEND_STRL ("payload" ), & zpayload );
1699
+
1641
1700
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
1642
1701
ZEND_TRY_ASSIGN_REF_LONG (arg6 , sll .sll_ifindex );
1643
1702
break ;
1644
- */
1645
1703
#endif
1646
1704
default :
1647
1705
zend_argument_value_error (1 , "must be one of AF_UNIX, AF_INET, or AF_INET6" );
@@ -1752,7 +1810,7 @@ PHP_FUNCTION(socket_sendto)
1752
1810
1753
1811
retval = sendto(php_sock->bsd_socket, buf, ((size_t)len > buf_len) ? buf_len : (size_t)len, flags, (struct sockaddr *) &sin, sizeof(sin));
1754
1812
break;
1755
- */
1813
+ */
1756
1814
#endif
1757
1815
default :
1758
1816
zend_argument_value_error (1 , "must be one of AF_UNIX, AF_INET, or AF_INET6" );
0 commit comments