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 ;
@@ -1503,7 +1514,7 @@ PHP_FUNCTION(socket_recvfrom)
1503
1514
struct sockaddr_in6 sin6 ;
1504
1515
#endif
1505
1516
#ifdef AF_PACKET
1506
- // struct sockaddr_ll sll;
1517
+ struct sockaddr_ll sll ;
1507
1518
#endif
1508
1519
char addrbuf [INET6_ADDRSTRLEN ];
1509
1520
socklen_t slen ;
@@ -1532,6 +1543,12 @@ PHP_FUNCTION(socket_recvfrom)
1532
1543
RETURN_FALSE ;
1533
1544
}
1534
1545
1546
+ #ifdef AF_PACKET
1547
+ if (php_sock -> type == AF_PACKET && arg3 < 2048 ) {
1548
+ RETURN_FALSE ;
1549
+ }
1550
+ #endif
1551
+
1535
1552
recv_buf = zend_string_alloc (arg3 + 1 , 0 );
1536
1553
1537
1554
switch (php_sock -> type ) {
@@ -1610,14 +1627,14 @@ PHP_FUNCTION(socket_recvfrom)
1610
1627
break ;
1611
1628
#endif
1612
1629
#ifdef AF_PACKET
1613
- /*
1614
1630
case AF_PACKET :
1615
1631
// TODO expose and use proper ethernet frame type instead i.e. src mac, dst mac and payload to userland
1616
1632
// ditto for socket_sendto
1617
1633
slen = sizeof (sll );
1618
1634
memset (& sll , 0 , sizeof (sll ));
1619
1635
sll .sll_family = AF_PACKET ;
1620
1636
char ifrname [IFNAMSIZ ];
1637
+ zval zpayload ;
1621
1638
1622
1639
retval = recvfrom (php_sock -> bsd_socket , ZSTR_VAL (recv_buf ), arg3 , arg4 , (struct sockaddr * )& sll , (socklen_t * )& slen );
1623
1640
@@ -1626,20 +1643,61 @@ PHP_FUNCTION(socket_recvfrom)
1626
1643
zend_string_efree (recv_buf );
1627
1644
RETURN_FALSE ;
1628
1645
}
1629
- ZSTR_LEN(recv_buf) = retval;
1630
- ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
1631
1646
1632
1647
if (UNEXPECTED (!if_indextoname (sll .sll_ifindex , ifrname ))) {
1633
1648
PHP_SOCKET_ERROR (php_sock , "unable to get the interface name" , errno );
1634
1649
zend_string_efree (recv_buf );
1635
1650
RETURN_FALSE ;
1636
1651
}
1637
1652
1638
- ZEND_TRY_ASSIGN_REF_NEW_STR(arg2, recv_buf);
1653
+ struct ethhdr * e = (struct ethhdr * )ZSTR_VAL (recv_buf );
1654
+ unsigned short protocol = ntohs (e -> h_proto );
1655
+ unsigned char * payload = ((unsigned char * )e + sizeof (struct ethhdr ));
1656
+
1657
+ object_init_ex (arg2 , socket_ethinfo_ce );
1658
+ zend_update_property_string (Z_OBJCE_P (arg2 ), Z_OBJ_P (arg2 ), ZEND_STRL ("macsrc" ), ether_ntoa ((struct ether_addr * )e -> h_source ));
1659
+ zend_update_property_string (Z_OBJCE_P (arg2 ), Z_OBJ_P (arg2 ), ZEND_STRL ("macdst" ), ether_ntoa ((struct ether_addr * )e -> h_dest ));
1660
+ array_init (& zpayload );
1661
+
1662
+ switch (protocol ) {
1663
+ case ETH_P_IP : {
1664
+ struct iphdr * ip = (struct iphdr * )payload ;
1665
+ unsigned char * ipdata = payload + (ip -> ihl * 4 );
1666
+ struct in_addr s , d ;
1667
+ s .s_addr = ip -> saddr ;
1668
+ d .s_addr = ip -> daddr ;
1669
+ add_assoc_string (& zpayload , "ipsrc" , inet_ntoa (s ));
1670
+ add_assoc_string (& zpayload , "ipdst" , inet_ntoa (d ));
1671
+
1672
+ switch (ip -> protocol ) {
1673
+ case IPPROTO_TCP : {
1674
+ struct tcphdr * tcp = (struct tcphdr * )ipdata ;
1675
+ add_assoc_long (& zpayload , "portsrc" , ntohs (tcp -> th_sport ));
1676
+ add_assoc_long (& zpayload , "portdst" , ntohs (tcp -> th_dport ));
1677
+ break ;
1678
+ }
1679
+ case IPPROTO_UDP : {
1680
+ struct udphdr * udp = (struct udphdr * )ipdata ;
1681
+ add_assoc_long (& zpayload , "portsrc" , ntohs (udp -> uh_sport ));
1682
+ add_assoc_long (& zpayload , "portdst" , ntohs (udp -> uh_dport ));
1683
+ break ;
1684
+ }
1685
+ default :
1686
+ zend_value_error ("unsupported ip header protocol" );
1687
+ RETURN_THROWS ();
1688
+ }
1689
+ break ;
1690
+ }
1691
+ default :
1692
+ zend_value_error ("unsupported ethernet protocol" );
1693
+ RETURN_THROWS ();
1694
+ }
1695
+
1696
+ zend_update_property (Z_OBJCE_P (arg2 ), Z_OBJ_P (arg2 ), ZEND_STRL ("payload" ), & zpayload );
1697
+
1639
1698
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
1640
1699
ZEND_TRY_ASSIGN_REF_LONG (arg6 , sll .sll_ifindex );
1641
1700
break ;
1642
- */
1643
1701
#endif
1644
1702
default :
1645
1703
zend_argument_value_error (1 , "must be one of AF_UNIX, AF_INET, or AF_INET6" );
@@ -1751,7 +1809,7 @@ PHP_FUNCTION(socket_sendto)
1751
1809
1752
1810
retval = sendto(php_sock->bsd_socket, buf, ((size_t)len > buf_len) ? buf_len : (size_t)len, flags, (struct sockaddr *) &sin, sizeof(sin));
1753
1811
break;
1754
- */
1812
+ */
1755
1813
#endif
1756
1814
default :
1757
1815
zend_argument_value_error (1 , "must be one of AF_UNIX, AF_INET, or AF_INET6" );
0 commit comments