question

heavenlyuwu-0476 avatar image
0 Votes"
heavenlyuwu-0476 asked XiaopoYang-MSFT edited

How to properly use NmAddFilter and NmAddField functions when writing an app using NmApi?

I'm trying to make an executable which can use the functionality provided by Network Monitor 3.4 API. So far I've managed to successfully record traffic, but now I'm attempting to preform analysis on the live data before it will be recorded. I try to use examples provided in the in-app documentation but its not always possible due to language difference (I'm writing mine in rust).

Although the binding seem to work fine, and I guess It's more a question of me misinterpreting the function call or something...

below is the stripped down version of my code:


 #![allow(non_camel_case_types, non_snake_case)]
    
 use cpp_xport::core_funcs::NMAPI::{NmCreateCaptureFile, NmOpenCaptureEngine, NmConfigAdapter, NmStopCapture, NmCloseHandle, NmAddFrame, NmStartCapture, NmGetAdapterCount, NmLoadNplParser, NmAddFilter, NmCreateFrameParserConfiguration, NmAddField, NmCreateFrameParser, NmParseFrame, NmEvaluateFilter, NmGetFieldValueString};
 use cpp_xport::shared::types::*;
 use std::mem::zeroed;
 use std::thread::sleep;
 use std::time::{Duration, SystemTime};
 use cpp_xport::util::WideString::{ToWide, FromWide};
 use std::ptr::null_mut;
 use cpp_xport::shared::types::NmNplParserLoadingOption::NmAppendRegisteredNplSets;
 use cpp_xport::shared::types::NmFrameParserOptimizeOption::NmParserOptimizeNone;
 use std::ops::AddAssign;
 use cpp_xport::shared::types::BOOL::{FALSE, TRUE};
    
 /// Wi-Fi network interface
 pub const adapter_idx: ULONG = 4;
    
    
 /// struct for passing handles to callback
 pub struct HandleBundle {
     pub frames_elapsed: ULONG,
     pub integrity_check: &'static str,  //'// to cancel the highlight, rust lifetime character is misinterpreted for string start or something
     pub cap_file: HANDLE,
     pub frame_parser: HANDLE,
     pub filter_id: ULONG,
     pub field_id: ULONG,
 }
    
    
 /// on frame callback
 pub unsafe extern "system" fn _MyFrameIndication(hCaptureEngine: HANDLE, adapterIndex: ULONG, pContext:  LPVOID, hRawFrame: HANDLE) {
    
    
     /// getting the HandleBundle
     let handle_bundle: &mut HandleBundle = (pContext as *mut HandleBundle).as_mut().unwrap();
     println!("integrity check, handle bundle says: {}", handle_bundle.integrity_check);
    
    
     /// frame preprocessing
     let mut parsed_frame: HANDLE = unsafe {zeroed()};
     let ret = unsafe { NmParseFrame(handle_bundle.frame_parser, hRawFrame, handle_bundle.frames_elapsed,
                                     0, &mut parsed_frame, null_mut())
     };
     handle_bundle.frames_elapsed.add_assign(1); /// incrementing frame count by 1
     println!("NmParseFrame: {}",ret);
     assert_eq!(ret, 0);
    
    
     /// using the filter added to evaluate the frame data
     let mut passed: BOOL = FALSE;
     let ret = unsafe {
         NmEvaluateFilter(parsed_frame,
                          handle_bundle.filter_id,
                          &mut passed)
     };
     println!("NmEvaluateFilter: {}",ret);
     assert_eq!(ret, 0);
    
    
     /// if the frame data triggers our filter
     if passed == TRUE {
    
    
         /// extracting the value from the added field into string buffer
         let mut string_buffer: Vec<u16> = vec![0_u16;256]; /// making a wide string buffer of known length
         let ret = unsafe {
             NmGetFieldValueString(parsed_frame,
                                   handle_bundle.field_id,
                                   256,
                                   string_buffer.as_mut_ptr())
         };
         println!("NmGetFieldValueString: {}", ret);
         assert_eq!(ret, 0);
    
    
         /// outputting the value
         println!("field value: {}", FromWide(string_buffer.as_mut_ptr(), 256));
    
     }
    
    
     /// releasing the parsed frame handle
     unsafe {
         NmCloseHandle(parsed_frame)
     };
    
    
     /// storing the raw frame in the capture file
     let ret = unsafe {
         NmAddFrame(handle_bundle.cap_file, hRawFrame)
     };
     println!("NmAddFrame: {}",ret);
     assert_eq!(ret, 0);
    
    
     /// releasing the raw frame handle
     unsafe {
         NmCloseHandle(hRawFrame)
     };
    
    
 }
    
    
 /// build (on init) callback
 pub unsafe extern "system" fn _onBuild(_: PVOID, _: ULONG, _: LPCWSTR, _: ULONG) {
     println!("on init called");
 }
    
    
    
 fn main () {
    
     /// opening a file to store the capture
     let mut myCapFile: HANDLE = unsafe { zeroed() };
     let mut CapSize: ULONG = unsafe { zeroed() };
     let mut pname: Vec<u16> = ToWide("C:\\Users\\grass\\Desktop\\codes\\Rust\\cpp_xport\\res\\20sec.cap");
     let ret = unsafe { NmCreateCaptureFile(pname.as_mut_ptr(), 2000,
                                            0, &mut myCapFile as PHANDLE, &mut CapSize)
     };
     println!("NmCreateCaptureFile: {}", ret);
     assert_eq!(ret, 0);
    
    
     /// initializing the capture engine
     let mut myCaptureEngine: HANDLE = unsafe { zeroed() };
     let ret = unsafe { NmOpenCaptureEngine(&mut myCaptureEngine) };
     println!("NmOpenCaptureEngine: {}", ret);
     assert_eq!(ret, 0);
    
    
    
     // =============================================================================================
    
     /// loads configuration language parser
     let mut parser: HANDLE = unsafe {zeroed()};
     let ret = unsafe { NmLoadNplParser(null_mut(),
                                        NmAppendRegisteredNplSets,
                                        Some(_onBuild),
                                        null_mut(), &mut parser) };
     println!("NmLoadNplParser: {}",ret);
     assert_eq!(ret, 0);
    
    
     /// creates a frame parser config
     let mut parser_config: HANDLE = unsafe {zeroed()};
     let ret = unsafe { NmCreateFrameParserConfiguration(parser,
                                                         Some(_onBuild),
                                                         null_mut(),
                                                         &mut parser_config) };
     println!("NmCreateFrameParserConfiguration: {}",ret);
     assert_eq!(ret, 0);
    
    
     /// adds a filtering rule to the frame parser config
     let mut rule = ToWide("http.request.command == \"GET\"");
     let mut filter_id: ULONG = 0;
     let ret = unsafe { NmAddFilter(parser_config,
                                    rule.as_mut_ptr(),
                                    &mut filter_id)
     };
     println!("NmAddFilter: {}",ret);
     assert_eq!(ret, 0);
    
    
     /// enables optimized access to the selected fields (http.request.uri in this case)
     let mut field_id: ULONG = 0;
     let ret = unsafe {
         let mut eq_string = ToWide("http.request.uri");
         NmAddField(parser_config,
                    eq_string.as_mut_ptr(),
                    &mut field_id)
    
     };
     println!("NmAddField: {}", ret);
     assert_eq!(ret, 0);
    
    
     /// creates the frame parser
     let mut frame_parser: HANDLE = unsafe {zeroed()};
     let ret = unsafe {
         NmCreateFrameParser(parser_config,
                             &mut frame_parser,
                             NmParserOptimizeNone)
     };
     println!("NmCreateFrameParser: {}", ret);
     assert_eq!(ret, 0);
    
     // =============================================================================================
    
    
     /// getting the number of available network interfaces
     let mut total_ifaces: ULONG = unsafe { zeroed() };
     let ret = unsafe { NmGetAdapterCount(myCaptureEngine, &mut total_ifaces as PULONG) };
     println!("NmGetAdapterCount: {}", ret);
     assert_eq!(ret, 0);
     println!("{} network interfaces are available", total_ifaces);
    
    
     /// configuring network monitor to use certain adapter, and assign per frame callback
     /// using pCallerContext to pass a bundle with handles
     let mut handle_bundle: HandleBundle = HandleBundle {
         frames_elapsed: 0,
         integrity_check: "hewwo, warudo",
         cap_file: myCapFile,
         frame_parser: frame_parser,
         filter_id: filter_id,
         field_id: field_id,
     };
     let ret = unsafe { NmConfigAdapter(myCaptureEngine,
                                        adapter_idx,
                                        Some(_MyFrameIndication),
                                        &mut handle_bundle as *mut _ as _,
                                        NmCaptureCallbackExitMode::DiscardRemainFrames)
     };
     println!("configuring adapter: code is {}", ret);
     assert_eq!(ret, 0);
    
    
     /// starting capture
     let ret = unsafe {
         NmStartCapture(myCaptureEngine,
                        adapter_idx,
                        NmAdapterCaptureMode::NmLocalOnly)
     };
     println!("starting capture: code is {}",ret);
     assert_eq!(ret, 0);
    
     // =============================================================================================
    
    
     /// wasting time
     let before = SystemTime::now();
     while (SystemTime::now().duration_since(before).unwrap().as_secs() < 25) {
    
     }
    
     // =============================================================================================
    
    
     println!("stopping capture");
    
     /// closing the capture
     unsafe {
         NmStopCapture(myCaptureEngine, adapter_idx)
     };
    
     println!("releasing handles");
    
     /// releasing the capture engine and file
     unsafe {
         NmCloseHandle(myCaptureEngine);
         NmCloseHandle(myCapFile);
     }
    
     // =============================================================================================
 }

to ensure i have the traffic needed for testing - I've created and ran in parallel the following python script:

 import requests
 from kivy.app import App
 from kivy.uix.label import Label
 from kivy.clock import Clock
    
    
 class MyApp(App):
     def build(self):
         self.dot_counter = 0
         self.lbl = Label(text="hello")
         Clock.schedule_interval(self.update_status_code, 1)
         return self.lbl
    
     def update_status_code(self, *args):
         self.lbl.text = str(requests.get("https://google.com").status_code)+("."*self.dot_counter)
         self.dot_counter = self.dot_counter + 1 if self.dot_counter < 4 else 0
    
    
 if __name__ == '__main__':
     MyApp().run()



Still I cant get the NmEvaluateFilter function to output true.

not-supported
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

0 Answers