@@ -52,7 +52,17 @@ const net_ebpf_extension_wfp_filter_parameters_t _net_ebpf_extension_sock_ops_wf
5252 NULL , // Default sublayer.
5353 & EBPF_HOOK_ALE_FLOW_ESTABLISHED_V6_CALLOUT ,
5454 L"net eBPF sock_ops hook" ,
55- L"net eBPF sock_ops hook WFP filter" }};
55+ L"net eBPF sock_ops hook WFP filter" },
56+ {& FWPM_LAYER_ALE_AUTH_LISTEN_V4 ,
57+ NULL , // Default sublayer.
58+ & EBPF_HOOK_ALE_AUTH_LISTEN_V4_CALLOUT ,
59+ L"net eBPF sock_ops listen hook" ,
60+ L"net eBPF sock_ops listen hook WFP filter" },
61+ {& FWPM_LAYER_ALE_AUTH_LISTEN_V6 ,
62+ NULL , // Default sublayer.
63+ & EBPF_HOOK_ALE_AUTH_LISTEN_V6_CALLOUT ,
64+ L"net eBPF sock_ops listen hook" ,
65+ L"net eBPF sock_ops listen hook WFP filter" }};
5666
5767#define NET_EBPF_SOCK_OPS_FILTER_COUNT EBPF_COUNT_OF(_net_ebpf_extension_sock_ops_wfp_filter_parameters)
5868
@@ -386,6 +396,27 @@ wfp_ale_layer_fields_t wfp_flow_established_fields[] = {
386396 FWPS_FIELD_ALE_FLOW_ESTABLISHED_V6_COMPARTMENT_ID ,
387397 FWPS_FIELD_ALE_FLOW_ESTABLISHED_V6_IP_LOCAL_INTERFACE }};
388398
399+ // WFP layer fields for listen hooks
400+ wfp_ale_layer_fields_t wfp_auth_listen_fields [] = {
401+ // EBPF_HOOK_ALE_AUTH_LISTEN_V4
402+ {FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_ADDRESS ,
403+ FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_PORT ,
404+ 0 , // No remote address for listen
405+ 0 , // No remote port for listen
406+ 0 , // No protocol field for listen layer
407+ 0 , // No direction field for listen (always inbound)
408+ FWPS_FIELD_ALE_AUTH_LISTEN_V4_COMPARTMENT_ID ,
409+ FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_INTERFACE },
410+ // EBPF_HOOK_ALE_AUTH_LISTEN_V6
411+ {FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_ADDRESS ,
412+ FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_PORT ,
413+ 0 , // No remote address for listen
414+ 0 , // No remote port for listen
415+ 0 , // No protocol field for listen layer
416+ 0 , // No direction field for listen (always inbound)
417+ FWPS_FIELD_ALE_AUTH_LISTEN_V6_COMPARTMENT_ID ,
418+ FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_INTERFACE }};
419+
389420static void
390421_net_ebpf_extension_sock_ops_copy_wfp_connection_fields (
391422 _In_ const FWPS_INCOMING_VALUES * incoming_fixed_values ,
@@ -437,6 +468,53 @@ _net_ebpf_extension_sock_ops_copy_wfp_connection_fields(
437468 }
438469}
439470
471+ static void
472+ _net_ebpf_extension_sock_ops_copy_wfp_listen_fields (
473+ _In_ const FWPS_INCOMING_VALUES * incoming_fixed_values ,
474+ _In_ const FWPS_INCOMING_METADATA_VALUES * incoming_metadata_values ,
475+ _Out_ net_ebpf_sock_ops_t * sock_ops_context )
476+ {
477+ uint16_t wfp_layer_id = incoming_fixed_values -> layerId ;
478+ net_ebpf_extension_hook_id_t hook_id = net_ebpf_extension_get_hook_id_from_wfp_layer_id (wfp_layer_id );
479+ wfp_ale_layer_fields_t * fields = & wfp_auth_listen_fields [hook_id - EBPF_HOOK_ALE_AUTH_LISTEN_V4 ];
480+ bpf_sock_ops_t * sock_ops = & sock_ops_context -> context ;
481+
482+ FWPS_INCOMING_VALUE0 * incoming_values = incoming_fixed_values -> incomingValue ;
483+
484+ // Listen operations are always of type BPF_SOCK_OPS_LISTEN_CB
485+ sock_ops -> op = BPF_SOCK_OPS_LISTEN_CB ;
486+
487+ // Copy IP address fields.
488+ if (hook_id == EBPF_HOOK_ALE_AUTH_LISTEN_V4 ) {
489+ sock_ops -> family = AF_INET ;
490+ sock_ops -> local_ip4 = htonl (incoming_values [fields -> local_ip_address_field ].value .uint32 );
491+ sock_ops -> remote_ip4 = 0 ; // No remote address for listen
492+ } else {
493+ sock_ops -> family = AF_INET6 ;
494+ RtlCopyMemory (
495+ sock_ops -> local_ip6 ,
496+ incoming_values [fields -> local_ip_address_field ].value .byteArray16 ,
497+ sizeof (FWP_BYTE_ARRAY16 ));
498+ memset (sock_ops -> remote_ip6 , 0 , sizeof (sock_ops -> remote_ip6 )); // No remote address for listen
499+ }
500+ sock_ops -> local_port = htons (incoming_values [fields -> local_port_field ].value .uint16 );
501+ sock_ops -> remote_port = 0 ; // No remote port for listen
502+ sock_ops -> protocol = IPPROTO_TCP ; // Listen operations are typically TCP
503+ sock_ops -> compartment_id = incoming_values [fields -> compartment_id_field ].value .uint32 ;
504+ sock_ops -> interface_luid = * incoming_values [fields -> interface_luid_field ].value .uint64 ;
505+ if (incoming_metadata_values -> currentMetadataValues & FWPS_METADATA_FIELD_PROCESS_ID ) {
506+ sock_ops_context -> process_id = incoming_metadata_values -> processId ;
507+ } else {
508+ NET_EBPF_EXT_LOG_MESSAGE_UINT64 (
509+ NET_EBPF_EXT_TRACELOG_LEVEL_VERBOSE ,
510+ NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS ,
511+ "FWPS_METADATA_FIELD_PROCESS_ID not present" ,
512+ hook_id );
513+
514+ sock_ops_context -> process_id = 0 ;
515+ }
516+ }
517+
440518//
441519// WFP callout callback function.
442520//
@@ -624,6 +702,100 @@ net_ebpf_extension_sock_ops_flow_delete(uint16_t layer_id, uint32_t callout_id,
624702 }
625703}
626704
705+ //
706+ // WFP classifyFn callback function for listen operations.
707+ //
708+ void
709+ net_ebpf_extension_sock_ops_listen_classify (
710+ _In_ const FWPS_INCOMING_VALUES * incoming_fixed_values ,
711+ _In_ const FWPS_INCOMING_METADATA_VALUES * incoming_metadata_values ,
712+ _Inout_opt_ void * layer_data ,
713+ _In_opt_ const void * classify_context ,
714+ _In_ const FWPS_FILTER * filter ,
715+ uint64_t flow_context ,
716+ _Inout_ FWPS_CLASSIFY_OUT * classify_output )
717+ {
718+ uint32_t result ;
719+ net_ebpf_extension_sock_ops_wfp_filter_context_t * filter_context = NULL ;
720+ net_ebpf_sock_ops_t sock_ops_context = {0 };
721+ uint32_t client_compartment_id = UNSPECIFIED_COMPARTMENT_ID ;
722+ ebpf_result_t program_result ;
723+
724+ UNREFERENCED_PARAMETER (layer_data );
725+ UNREFERENCED_PARAMETER (classify_context );
726+ UNREFERENCED_PARAMETER (flow_context );
727+
728+ NET_EBPF_EXT_LOG_ENTRY ();
729+
730+ classify_output -> actionType = FWP_ACTION_PERMIT ;
731+
732+ filter_context = (net_ebpf_extension_sock_ops_wfp_filter_context_t * )filter -> context ;
733+ ASSERT (filter_context != NULL );
734+ if (filter_context == NULL ) {
735+ goto Exit ;
736+ }
737+
738+ if (filter_context -> base .context_deleting ) {
739+ NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS (
740+ NET_EBPF_EXT_TRACELOG_LEVEL_VERBOSE ,
741+ NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS ,
742+ "net_ebpf_extension_sock_ops_listen_classify - Client detach detected." ,
743+ STATUS_INVALID_PARAMETER );
744+ goto Exit ;
745+ }
746+
747+ // Copy WFP fields for listen operation
748+ _net_ebpf_extension_sock_ops_copy_wfp_listen_fields (
749+ incoming_fixed_values , incoming_metadata_values , & sock_ops_context );
750+
751+ client_compartment_id = filter_context -> compartment_id ;
752+ ASSERT (
753+ (client_compartment_id == UNSPECIFIED_COMPARTMENT_ID ) ||
754+ (client_compartment_id == sock_ops_context .context .compartment_id ));
755+ if (client_compartment_id != UNSPECIFIED_COMPARTMENT_ID &&
756+ client_compartment_id != sock_ops_context .context .compartment_id ) {
757+ // The client is not interested in this compartment Id.
758+ NET_EBPF_EXT_LOG_MESSAGE_UINT32 (
759+ NET_EBPF_EXT_TRACELOG_LEVEL_VERBOSE ,
760+ NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS ,
761+ "The sock_ops eBPF program is not interested in this compartmentId" ,
762+ sock_ops_context .context .compartment_id );
763+ goto Exit ;
764+ }
765+
766+ program_result = net_ebpf_extension_hook_invoke_programs (& sock_ops_context .context , & filter_context -> base , & result );
767+ if (program_result == EBPF_OBJECT_NOT_FOUND ) {
768+ // No program is attached to this hook.
769+ NET_EBPF_EXT_LOG_MESSAGE (
770+ NET_EBPF_EXT_TRACELOG_LEVEL_WARNING ,
771+ NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS ,
772+ "net_ebpf_extension_sock_ops_listen_classify - No attached client." );
773+ goto Exit ;
774+ } else if (program_result != EBPF_SUCCESS ) {
775+ NET_EBPF_EXT_LOG_MESSAGE_UINT32 (
776+ NET_EBPF_EXT_TRACELOG_LEVEL_ERROR ,
777+ NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS ,
778+ "net_ebpf_extension_sock_ops_listen_classify - Program invocation failed." ,
779+ program_result );
780+ goto Exit ;
781+ }
782+
783+ // For listen operations, the result determines whether to allow or block the listen operation
784+ classify_output -> actionType = (result == 0 ) ? FWP_ACTION_PERMIT : FWP_ACTION_BLOCK ;
785+ if (classify_output -> actionType == FWP_ACTION_BLOCK ) {
786+ classify_output -> rights &= ~FWPS_RIGHT_ACTION_WRITE ;
787+ }
788+
789+ NET_EBPF_EXT_LOG_MESSAGE_UINT32 (
790+ NET_EBPF_EXT_TRACELOG_LEVEL_VERBOSE ,
791+ NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_OPS ,
792+ "Listen operation processed, port:" ,
793+ sock_ops_context .context .local_port );
794+
795+ Exit :
796+ NET_EBPF_EXT_LOG_EXIT ();
797+ }
798+
627799static ebpf_result_t
628800_ebpf_sock_ops_context_create (
629801 _In_reads_bytes_opt_ (data_size_in ) const uint8_t * data_in ,
0 commit comments