ANSC_STATUS
BbhmDiagipRecv
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSinkObject,
        PVOID                       buffer,
        ULONG                       ulSize
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PBBHM_DIAG_IP_PING_OBJECT       pMyObject    = (PBBHM_DIAG_IP_PING_OBJECT)hThisObject;
    PBBHM_IP_PING_PROPERTY          pProperty    = (PBBHM_IP_PING_PROPERTY        )&pMyObject->Property;
    PBBHM_IP_PING_TDO_OBJECT        pStateTimer  = (PBBHM_IP_PING_TDO_OBJECT      )pMyObject->hStateTimer;
    PBBHM_IP_PING_SINK_OBJECT       pSink        = (PBBHM_IP_PING_SINK_OBJECT     )hSinkObject;
    PANSC_XSOCKET_OBJECT            pSocket      = (PANSC_XSOCKET_OBJECT          )pSink->GetXsocket((ANSC_HANDLE)pSink);
    PIPV4_HEADER                    pIpv4Header  = (PIPV4_HEADER                  )NULL;
    /*PIPV6_HEADER                    pIpv6Header  = (PIPV6_HEADER                  )NULL;*/
    PICMPV4_ECHO_MESSAGE            pIcmpHeader  = (PICMPV4_ECHO_MESSAGE          )NULL;
    PBBHM_IP_PING_ECHO_ENTRY        pMEchoEntry  = NULL;
    ULONG                           StopTime     = 0;

    StopTime = AnscGetTickInMilliSeconds();

    if ( pProperty->Status != BBHM_IP_PING_STATUS_RUNNING )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }

    if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET )
    {
        pIpv4Header = (PIPV4_HEADER)buffer;
        pIcmpHeader = (PICMPV4_ECHO_MESSAGE)AnscIpv4GetPayload(pIpv4Header);

        if ( ! AnscEqualString(pSocket->PeerName, pProperty->pDstAddrName, TRUE)/*(pSocket->PeerAddress.Value != pProperty->DstIp.Value)*/
            || (AnscIcmpv4EchoGetId(pIcmpHeader) !=  tempId) )
        {
            return  ANSC_STATUS_FAILURE;
        }

        if ( (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_DESTINATION_UNREACHABLE)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_TIME_EXCEEDED)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_PARAMETER_PROBLEM)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_SOURCE_QUENCH)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_REDIRECT))
        {
            pProperty->NumIcmpError ++;
            pProperty->IcmpError = AnscIcmpv4EchoGetType(pIcmpHeader);

            pMEchoEntry = (PBBHM_IP_PING_ECHO_ENTRY)AnscAllocateMemory(sizeof(BBHM_IP_PING_ECHO_ENTRY));
            if ( pMEchoEntry )
            {
                pMEchoEntry->ICMPType = AnscIcmpv4EchoGetType(pIcmpHeader);
                AnscAcquireLock(&pMyObject->MiddleResultLock);
                AnscSListPushEntryAtBack(&pMyObject->MiddleResult, &pMEchoEntry->Linkage);
                AnscReleaseLock(&pMyObject->MiddleResultLock);
            }

            return  ANSC_STATUS_FAILURE;
        }

        returnStatus =
            pMyObject->SetStopTime
                (
                    (ANSC_HANDLE)pMyObject,
                    AnscIcmpv4EchoGetSeqNumber(pIcmpHeader),
                    AnscIpv4GetTotalLength(pIpv4Header) - sizeof(IPV4_HEADER) - sizeof(ICMPV4_HEADER),
                    AnscIpv4GetTtl(pIpv4Header),
                    StopTime
                );
    }
    else if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET6 )
    {
        pIcmpHeader = (PICMPV6_ECHO_MESSAGE)buffer;

        if ( ! AnscEqualString(pSocket->PeerName, pProperty->pDstAddrName, TRUE)/*(pSocket->PeerAddress.Value != pProperty->DstIp.Value)*/
            || (AnscIcmpv6EchoGetId(pIcmpHeader) !=  tempId) )
        {
            return  ANSC_STATUS_FAILURE;
        }

        if ( (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_DESTINATION_UNREACHABLE)
            || (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_TIME_EXCEEDED)
            || (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_PARAMETER_PROBLEM)
            || (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_PACKET_TOO_BIG))
        {
            pProperty->NumIcmpError ++;
            pProperty->IcmpError = AnscIcmpv6EchoGetType(pIcmpHeader);

            pMEchoEntry = (PBBHM_IP_PING_ECHO_ENTRY)AnscAllocateMemory(sizeof(BBHM_IP_PING_ECHO_ENTRY));
            if ( pMEchoEntry )
            {
                pMEchoEntry->ICMPType = AnscIcmpv6EchoGetType(pIcmpHeader);
                AnscAcquireLock(&pMyObject->MiddleResultLock);
                AnscSListPushEntryAtBack(&pMyObject->MiddleResult, &pMEchoEntry->Linkage);
                AnscReleaseLock(&pMyObject->MiddleResultLock);
            }

            return  ANSC_STATUS_FAILURE;
        }

        returnStatus =
            pMyObject->SetStopTime
                (
                    (ANSC_HANDLE)pMyObject,
                    AnscIcmpv6EchoGetSeqNumber(pIcmpHeader),
                    ulSize,
                    0,           /* Hop Limit */
                    StopTime
                );
    }

    if ( returnStatus == ANSC_STATUS_SUCCESS )
    {
        pProperty->PktsRecv ++;
    }

    if ( pProperty->PktsRecv == pProperty->NumPkts )
    {
        pMyObject->SetStatus((ANSC_HANDLE)pMyObject, BBHM_IP_PING_STATUS_COMPLETE);
        pMyObject->Stop((ANSC_HANDLE)pMyObject);
    }

    return  returnStatus;
}
void
AnscTraceIpPacket
    (
        ANSC_HANDLE                 hIpPacket
    )
{
    ANSC_STATUS                     returnStatus        = ANSC_STATUS_SUCCESS;
    PIPV4_HEADER                    pIp4Header          = (PIPV4_HEADER)hIpPacket;
    PUDP_HEADER                     pUdpHeader          = (PUDP_HEADER)AnscIpv4GetPayload(pIp4Header);
    PTCP_HEADER                     pTcpHeader          = (PTCP_HEADER)pUdpHeader;
    PICMPV4_HEADER                  pIcmpHeader;

    PUCHAR                          pTpPayload;
    ULONG                           ulTpPayloadLen;
    char                            TcpFlagStr[7]       = "      \0";

    ULONG                           ulTimeStamp;
    ULONG                           seconds;
    ULONG                           mSeconds;

    ULONG                           currentOffset       = 0;
    ULONG                           ulFragmentSize      = 0;

    /*
     *  get current time
     */
    ulTimeStamp = AnscGetTickInMilliSeconds();

    seconds     = ulTimeStamp;
    mSeconds    = ulTimeStamp % 1000;

    /*
     *  print the packet
     */
    AnscTraceWrapper
        (
            "%u.%03u IP: len = %d, ",
            seconds,
            mSeconds,
            AnscIpv4GetTotalLength(pIp4Header)
        );

    pIcmpHeader  = (PICMPV4_HEADER)pUdpHeader;

    if ( !AnscIpv4IsFragment(pIp4Header) || (AnscIpv4IsFragment(pIp4Header) && AnscIpv4IsFirstFragment(pIp4Header)))
    {
        if(AnscIpv4GetTransportType(pIp4Header) == TCP_TRANSPORT)
        {
            AnscTraceWrapper
                (
                    "protocol=%d, src=%d.%d.%d.%d:%d, dest=%d.%d.%d.%d:%d ",
                    AnscIpv4GetTransportType(pIp4Header),
                    AnscIpv4GetSrcAddressDot(pIp4Header)[0],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[1],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[2],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[3],
                    AnscTcpGetSrcPort(pTcpHeader),
                    AnscIpv4GetDstAddressDot(pIp4Header)[0],
                    AnscIpv4GetDstAddressDot(pIp4Header)[1],
                    AnscIpv4GetDstAddressDot(pIp4Header)[2],
                    AnscIpv4GetDstAddressDot(pIp4Header)[3],
                    AnscTcpGetDstPort(pTcpHeader)
                );

            if (AnscTcpIsUrg(pTcpHeader))
            {
                TcpFlagStr[0] = 'U';
            }
            if (AnscTcpIsAck(pTcpHeader))
            {
                TcpFlagStr[1] = 'A';
            }
            if (AnscTcpIsPsh(pTcpHeader))
            {
                TcpFlagStr[2] = 'P';
            }
            if (AnscTcpIsRst(pTcpHeader))
            {
                TcpFlagStr[3] = 'R';
            }
            if (AnscTcpIsSyn(pTcpHeader))
            {
                TcpFlagStr[4] = 'S';
            }
            if (AnscTcpIsFin(pTcpHeader))
            {
                TcpFlagStr[5] = 'F';
            }
            TcpFlagStr[6] = 0;

            AnscTraceWrapper
                (
                    " %s ",
                    TcpFlagStr
                );

            pTpPayload      = AnscTcpGetPayload(pTcpHeader);
            ulTpPayloadLen  = AnscIpv4GetTotalLength(pIp4Header) - ((ULONG)pTpPayload - (ULONG)pIp4Header);

            AnscTraceWrapper
                (
                    "Seq=%u~%u, Ack=%u",
                    AnscTcpGetSeqNumber(pTcpHeader),
                    AnscTcpGetSeqNumber(pTcpHeader) + ulTpPayloadLen,
                    AnscTcpGetAckNumber(pTcpHeader)
                );
        }
        else if (AnscIpv4GetTransportType(pIp4Header) == UDP_TRANSPORT)
        {
            AnscTraceWrapper
                (
                    "protocol=%d, src=%d.%d.%d.%d:%d, dest=%d.%d.%d.%d:%d",
                    AnscIpv4GetTransportType(pIp4Header),
                    AnscIpv4GetSrcAddressDot(pIp4Header)[0],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[1],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[2],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[3],
                    AnscUdpGetSrcPort(pUdpHeader),
                    AnscIpv4GetDstAddressDot(pIp4Header)[0],
                    AnscIpv4GetDstAddressDot(pIp4Header)[1],
                    AnscIpv4GetDstAddressDot(pIp4Header)[2],
                    AnscIpv4GetDstAddressDot(pIp4Header)[3],
                    AnscUdpGetDstPort(pUdpHeader)
                );
        }
        else if (AnscIpv4GetTransportType(pIp4Header) == ICMP_TRANSPORT)
        {
            AnscTraceWrapper
                (
                    "protocol=%d, src=%d.%d.%d.%d, dest=%d.%d.%d.%d, type=%d",
                    AnscIpv4GetTransportType(pIp4Header),
                    AnscIpv4GetSrcAddressDot(pIp4Header)[0],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[1],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[2],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[3],
                    AnscIpv4GetDstAddressDot(pIp4Header)[0],
                    AnscIpv4GetDstAddressDot(pIp4Header)[1],
                    AnscIpv4GetDstAddressDot(pIp4Header)[2],
                    AnscIpv4GetDstAddressDot(pIp4Header)[3],
                    AnscIcmpv4GetType(pIcmpHeader)
                );
        }
        else
        {
            AnscTraceWrapper
                (
                    "protocol=%d, src=%d.%d.%d.%d, dest=%d.%d.%d.%d",
                    AnscIpv4GetTransportType(pIp4Header),
                    AnscIpv4GetSrcAddressDot(pIp4Header)[0],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[1],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[2],
                    AnscIpv4GetSrcAddressDot(pIp4Header)[3],
                    AnscIpv4GetDstAddressDot(pIp4Header)[0],
                    AnscIpv4GetDstAddressDot(pIp4Header)[1],
                    AnscIpv4GetDstAddressDot(pIp4Header)[2],
                    AnscIpv4GetDstAddressDot(pIp4Header)[3]
                );
        }
    }
    else
    {
        AnscTraceWrapper
            (
                "IP: protocol=%d, src=%d.%d.%d.%d, dest=%d.%d.%d.%d ",
                AnscIpv4GetTransportType(pIp4Header),
                AnscIpv4GetSrcAddressDot(pIp4Header)[0],
                AnscIpv4GetSrcAddressDot(pIp4Header)[1],
                AnscIpv4GetSrcAddressDot(pIp4Header)[2],
                AnscIpv4GetSrcAddressDot(pIp4Header)[3],
                AnscIpv4GetDstAddressDot(pIp4Header)[0],
                AnscIpv4GetDstAddressDot(pIp4Header)[1],
                AnscIpv4GetDstAddressDot(pIp4Header)[2],
                AnscIpv4GetDstAddressDot(pIp4Header)[3]
            );
    }

    if ( AnscIpv4GetTos(pIp4Header) != 0 )
    {
        AnscTraceWrapper(" Tos=0x%X", AnscIpv4GetTos(pIp4Header));
    }

    if ( AnscIpv4IsDontFragment(pIp4Header) )
    {
        AnscTraceWrapper(" DF");
    }

    AnscTraceWrapper(" TTL=%lu", AnscIpv4GetTtl(pIp4Header));

    if (!AnscIpv4IsFragment(pIp4Header))
    {
        AnscTraceWrapper("\n");
    }
    else
    {
        currentOffset       = AnscIpv4GetFragmentOffset(pIp4Header) * 8;
        ulFragmentSize      = (ULONG)AnscIpv4GetTotalLength(pIp4Header) - AnscIpv4GetHeaderSize(pIp4Header);

        AnscTraceWrapper
            (
                " id = %X, %d@%d\n",
                AnscIpv4GetId(pIp4Header),
                (int)ulFragmentSize,
                (int)currentOffset
            );
    }

    return;
}