locked
FwpsInjectNetworkSendAsync0 and DHCP RRS feed

  • Question

  • There is Windows 7 x64 with two network adapters. On Adapter1 IP-address was set  up manually, on Adapter2 by DHCP. Adapter1 is up, Adapter2 is down. In this system there is a WFP callout driver that uses “Out-of-band Packet Modification from Outbound Network Layers".

    When Adapter2 is getting up DHCP-request packets after re-injecting is outgoing from Adaper1. What’s wrong?


    // Create injection handle
    {
         FwpsInjectionHandleCreate0(
              AF_INET,
              FWPS_INJECTION_TYPE_NETWORK,
              &gInjectionHandle
              );
    }
    
    
    // Register filters
    {
    
         mCallout.calloutKey = IPLIR_OUTBOUND_CALLOUT;
         mCallout.displayData = displayData;
         mCallout.applicableLayer = FWPM_LAYER_OUTBOUND_IPPACKET_V4 ;
         mCallout.flags = FWPM_CALLOUT_FLAG_PERSISTENT;
    
         status = FwpmCalloutAdd0(
              engineHandle,
              &mCallout,
              NULL,
              NULL
              );
    
         if(status != ERROR_SUCCESS)
         {
              return status;
         }
    
         FWPM_FILTER0 filter = {0};
         FWPM_FILTER_CONDITION0 filterConditions[1] = {0}; 
         UINT conditionIndex;
    
         filter.layerKey = FWPM_LAYER_OUTBOUND_IPPACKET_V4;
         filter.displayData.name = L"IP-package entirely (Outbound)";
         filter.displayData.description = L"";
    
         filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
         filter.action.calloutKey = IPLIR_OUTBOUND_CALLOUT;
         filter.filterCondition = filterConditions;
         filter.subLayerKey = IPLIR_SUBLAYER;
         filter.weight.type = FWP_EMPTY; // auto-weight.
         filter.flags = FWPM_FILTER_FLAG_BOOTTIME | FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED;
    
         conditionIndex = 0;
    
         filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_FLAGS;
         filterConditions[conditionIndex].matchType = FWP_MATCH_FLAGS_NONE_SET;
         filterConditions[conditionIndex].conditionValue.type = FWP_UINT32;
         filterConditions[conditionIndex].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_LOOPBACK;
         conditionIndex++;
    
         filter.numFilterConditions = conditionIndex;
    
         status = FwpmFilterAdd0(
              engineHandle,
              &filter,
              NULL,
              NULL);
    
         if(status != ERROR_SUCCESS)
         {
              return status;
         }
    
         filter.flags = FWPM_FILTER_FLAG_PERSISTENT | FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED;
    
         status = FwpmFilterAdd0(
              engineHandle,
              &filter,
              NULL,
              NULL);
    
    }
    
    
    //  Classify callback
    
    OutboundClassifyCallback(
                             IN const FWPS_INCOMING_VALUES0* inFixedValues,
                             IN const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
                             IN OUT void* layerData,
                             IN const FWPS_FILTER0* filter,
                             IN UINT64 flowContext,
                             OUT FWPS_CLASSIFY_OUT0* classifyOut
                             )
    {
    
         if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
         {
              return;
         }
    
         UINT32 localAddress = inFixedValues->incomingValue[FWPS_FIELD_OUTBOUND_IPPACKET_V4_IP_LOCAL_ADDRESS].value.uint32;
         UINT32 remoteAddress = inFixedValues->incomingValue[FWPS_FIELD_OUTBOUND_IPPACKET_V4_IP_REMOTE_ADDRESS].value.uint32;
         PNET_LUID luidInterface = (PNET_LUID)inFixedValues->incomingValue[FWPS_FIELD_OUTBOUND_IPPACKET_V4_IP_LOCAL_INTERFACE].value.int64;
         UINT32 interfaceIndex = inFixedValues->incomingValue[FWPS_FIELD_OUTBOUND_IPPACKET_V4_INTERFACE_INDEX].value.uint32;
         UINT32 subInterfaceIndex = inFixedValues->incomingValue[FWPS_FIELD_OUTBOUND_IPPACKET_V4_SUB_INTERFACE_INDEX].value.uint32;
    
    
         HANDLE injectionContext = NULL;
         FWPS_PACKET_INJECTION_STATE packetState = FwpsQueryPacketInjectionState0(
              gInjectionHandle, netBufferList, &injectionContext );
    
         if( packetState == FWPS_PACKET_INJECTED_BY_SELF ||
              packetState == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF )
         {
    	  KdPrint(("Reinject\n"));
              KdPrint(("localAddress: %x\n", localAddress ));
              KdPrint(("remoteAddress: %x\n", remoteAddress ));
              KdPrint(("luidInterface: %I64x\n", *luidInterface ));
              KdPrint(("interfaceIndex: %x\n", interfaceIndex ));
              KdPrint(("subInterfaceIndex: %x\n", subInterfaceIndex ));
    
              classifyOut->actionType = FWP_ACTION_PERMIT;
              return;
         }
    
         KdPrint(("localAddress: %x\n", localAddress ));
         KdPrint(("remoteAddress: %x\n", remoteAddress ));
         KdPrint(("luidInterface: %I64x\n", *luidInterface ));
         KdPrint(("interfaceIndex: %x\n", interfaceIndex ));
         KdPrint(("subInterfaceIndex: %x\n", subInterfaceIndex ));
    
         NET_BUFFER_LIST *netBufferList = (NET_BUFFER_LIST*)layerData;
    
         //
         // Allocate and populate classifyInfo using information 
         // from inFixedValues and inMetaValues.
         //
         // .....
    
         FwpsReferenceNetBufferList0(netBufferList, TRUE);
         classifyInfo->origNetBufferList = netBufferList;
         classifyInfo->compartmentId = inMetaValues->compartmentId;
    
         //
         //  Queue classifyInfo for out-of-band processing.
         //
         // .....
    
         classifyOut->actionType = FWP_ACTION_BLOCK;
         classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
         classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
    
    }
    
    void WorkerThread( classifyInfo )
    {
         NET_BUFFER_LIST *netBufferList = NULL;
    
         FwpsAllocateCloneNetBufferList0(classifyInfo ->origNetBufferList
              , gNetBufferListPool, NULL, 0, &netBufferList );
    
         FwpsDereferenceNetBufferList0(classifyInfo->origNetBufferList, FALSE );
    
         FwpsInjectNetworkSendAsync0( gInjectionHandle, NULL, 0, classifyInfo-> compartmentId
              ,  netBufferList, IplirInjectionCompletionFn, NULL );
    }

    Result:

    localAddress: 0
    remoteAddress: ffffffff
    luidInterface: 6000009000000
    interfaceIndex: 14
    subInterfaceIndex: 0

    Reinject
    localAddress: 0
    remoteAddress: ffffffff
    luidInterface: 6000006000000
    interfaceIndex: b
    subInterfaceIndex: 0

    Tuesday, November 10, 2009 12:36 PM

Answers

All replies

  • FwpsInjectNetworkSendAsync0 has no control over from which I/F the packet would the packet will go out from.

    Try FwpsInjectTransportSendAsync0 -- you intercept the DHCP packet from outbound TRANSPORT layer and you re-inject using the same transportEndpointHandle (indicated from inMetaValues).

    Hope this helps,
    Biao.W.

    Thursday, November 12, 2009 6:42 AM
  • I can't see any DHCP-Request packets (source ip == 0x0 && destin ip == 0xffffffff) at FWPS_LAYER_OUTBOUND_TRANSPORT_V4.

    Back to the initial question – how can I use "Out-of-band Inspection/Modification Callout" to handle that packets.
    Thursday, November 19, 2009 7:52 AM
  • "I can't see any DHCP-Request packets (source ip == 0x0 && destin ip == 0xffffffff) at FWPS_LAYER_OUTBOUND_TRANSPORT_V4."

    You should be able to catch DHCP requests from OUTBOUND_TRANSPORT, can you share out your filter conditions at sublayer GUID for that layer?

    thanks,
    biao.w.
    Friday, November 20, 2009 3:45 AM
  • I see packages :). In the filter I had a condition ”matchType = FWP_MATCH_FLAGS_NONE_SET; conditionValue.uint32 = FWP_CONDITION_FLAG_IS_LOOPBACK;”. Why flag LOOPBACK is set for such packages on transport layer?

    But problems persist:

    • If I do FwpsConstructIpHeaderForTransportPacket0 then a package is outgoing from the wrong adapter.
    • If we not do FwpsConstructIpHeaderForTransportPacket0 how can we change IP protocol number?
    • Proposed as answer by SachinW Saturday, November 21, 2009 5:44 AM
    • Unproposed as answer by SachinW Saturday, November 21, 2009 7:13 AM
    • Edited by Santosh Kumar Nair Tuesday, November 24, 2009 1:03 AM Fixed HTML
    Friday, November 20, 2009 9:09 AM
  • Broadcast sender will receive its own broadcast (as loopback) so your condition simply means don't intercept those (which seems reasonable).
    You should not need to use FwpsConstructIpHeaderForTransportPacket0. You can simpy make a clone and call FwpsInjectTransportSendAsync0
    with the clone and the indicated inMetaValues->transportEndpointHandle.

    Thanks, Biao.W.
    Saturday, November 21, 2009 2:23 AM
  • > You can simpy make a clone and call FwpsInjectNetworkSendAsync0
    FwpsInjectTransportSendAsync0?

    How I can change IP protocol number?

    Monday, November 23, 2009 6:19 AM
  • sorry typo i meant FwpsInjectTransportSendAsync0.

    If you need to modify IP header then check out this thread. http://social.msdn.microsoft.com/Forums/en-US/wfp/thread/6c8bebf1-ef76-4495-8268-347071c8d247

    Biao.W.

    Monday, November 23, 2009 8:29 PM