Пример #1
0
static uint32_t ExDNSDG(DNSDG * pDNSDG, int16_t cbMax)
{
    bool        fMachineOrder   = DNSIsInMachineOrder(pDNSDG);
    uint8_t *   pRR             = pDNSDG->rrRecords;
    uint8_t *   pEnd            = ((uint8_t *) pDNSDG) + cbMax;
    uint16_t    cQD             = pDNSDG->dnsHdr.QDCOUNT;
    uint16_t    cRR             = pDNSDG->dnsHdr.ANCOUNT + pDNSDG->dnsHdr.NSCOUNT + pDNSDG->dnsHdr.ARCOUNT + cQD;
    uint16_t    i               = 0;

    // exchange the header
    // ExEndian(&pDNSDG->dnsHdr.ID, sizeof(pDNSDG->dnsHdr.ID));
    ExEndian(&pDNSDG->dnsHdr.QDCOUNT, sizeof(pDNSDG->dnsHdr.QDCOUNT));
    ExEndian(&pDNSDG->dnsHdr.ANCOUNT, sizeof(pDNSDG->dnsHdr.ANCOUNT));
    ExEndian(&pDNSDG->dnsHdr.NSCOUNT, sizeof(pDNSDG->dnsHdr.NSCOUNT));
    ExEndian(&pDNSDG->dnsHdr.ARCOUNT, sizeof(pDNSDG->dnsHdr.ARCOUNT));
    DNSToggleOrder(pDNSDG);
    
    // if we got the counts wrong before, get them correct now.
    if(!fMachineOrder)
    {
        cQD = pDNSDG->dnsHdr.QDCOUNT;
        cRR = pDNSDG->dnsHdr.ANCOUNT + pDNSDG->dnsHdr.NSCOUNT + pDNSDG->dnsHdr.ARCOUNT + cQD;
    }

    // now switch all of the answer records
    for(i=0; i < cRR && pRR < pEnd; i++)
    {
        pRR = ExDNSRRecord(pRR, (i < cQD), pEnd);
    }

    return(pRR - ((uint8_t *) pDNSDG));
}
Пример #2
0
static uint8_t * ExDNSRRecord(uint8_t * pRR, bool fQuestionRecord, uint8_t * pEnd)
{
    DNSRR *     pDNSRR = NULL;
    uint8_t *   pEx = DNSSkipName(pRR, pEnd);

    // skip past the name
    pDNSRR = (DNSRR *) pEx;
    pEx += (fQuestionRecord ? sizeof(DNSQRR) : sizeof(DNSRR));

    // this is an error case
    if(pEx > pEnd)
    {
        return(NULL);
    }

    ExEndian(&pDNSRR->TYPE, sizeof(pDNSRR->TYPE));
    ExEndian(&pDNSRR->CLASS, sizeof(pDNSRR->CLASS));

    if(!fQuestionRecord)
    {
        ExEndian(&pDNSRR->TTL, sizeof(pDNSRR->TTL));
        ExEndian(&pDNSRR->RDLENGTH, sizeof(pDNSRR->RDLENGTH));
        pEx += pDNSRR->RDLENGTH;
    }

    // went too far
    if(pEx > pEnd)
    {
        return(NULL);
    }

    return(pEx);
}
Пример #3
0
static void ExICMP0(void * pv, bool fStartsInMachineOrder)
{
    // indentifier
    ExEndian(pv, sizeof(uint16_t));
    pv += sizeof(uint16_t);

    // sequence
    ExEndian(pv, sizeof(uint16_t));
}
Пример #4
0
uint32_t ExICMP(void * pv, uint32_t cb, bool fStartsInMachineOrder)
{
    ICMPHDR *   pICMPHdr    = pv;
    ICMPTYPE    icmpType;
    
    uint32_t    cbRet       = 0;

    if(cb < sizeof(ICMPHDR)) return(0);

    if(fStartsInMachineOrder)
    {
        pICMPHdr->checksum = 0;
        icmpType = pICMPHdr->icmpType;
        ExEndian(&pICMPHdr->icmpType, sizeof(pICMPHdr->icmpType));
    }
    else
    {
        // checksum should be 0, otherwise there is an error.
        pICMPHdr->checksum = CalculateChecksum(0, pv, cb);
        ExEndian(&pICMPHdr->icmpType, sizeof(pICMPHdr->icmpType));
        icmpType = pICMPHdr->icmpType;
    }
    ExEndian(&pICMPHdr->code, sizeof(pICMPHdr->code));

    switch(icmpType)
    {
        case icmpTypeEcho:                  
        case icmpTypeEchoReply:
            if(cb < sizeof(ICMPT0)) return(0);
            ExICMP0(pv + sizeof(ICMPHDR), fStartsInMachineOrder);
            cbRet = cb; // don't know the length of the data, must trust what came in.
            break;
   
        case icmpTypeDestinationUnreachable:
        case icmpTypeSourceQuench:          
        case icmpTypeRedirect:              
        case icmpTypeTimeExceeded:          
        case icmpTypeParameterProblem:      
        case icmpTypeTimestamp:             
        case icmpTypeTimestampReply:        
        case icmpTypeInformationRequest:    
        case icmpTypeInformationReply:      
        default:
            return(0);
    }

    if(fStartsInMachineOrder)
    {
        // already in proper order
        pICMPHdr->checksum = CalculateChecksum(0, pv, cbRet);
    }

    return(cbRet);
}
Пример #5
0
uint32_t ExUDPHeader(IPSTACK * pIpStack, bool fStartsInMachineOrder)
{
    uint16_t sum = ~(ippnUDP << 8);

    // checksum of the psuedo header
    if(ILIsIPv6(pIpStack->pLLAdp))
    {
        sum = CalculateChecksum(sum, &pIpStack->pIPv6Hdr->ipSrc, sizeof(IPv6));
        sum = CalculateChecksum(sum, &pIpStack->pIPv6Hdr->ipDest, sizeof(IPv6));
    }
    else
    {
        sum = CalculateChecksum(sum, &pIpStack->pIPv4Hdr->ipSrc, sizeof(IPv4));
        sum = CalculateChecksum(sum, &pIpStack->pIPv4Hdr->ipDest, sizeof(IPv4));
    }

    // must put in network order, and do check sum
    if(fStartsInMachineOrder)
    {
        pIpStack->pUDPHdr->checksum = 0;    // set this to zero for calcluation
        ExEndian(&pIpStack->pUDPHdr->portSrc, sizeof(pIpStack->pUDPHdr->portSrc));
        ExEndian(&pIpStack->pUDPHdr->portDest, sizeof(pIpStack->pUDPHdr->portDest));
        ExEndian(&pIpStack->pUDPHdr->cbHdrData, sizeof(pIpStack->pUDPHdr->cbHdrData));
        sum = CalculateChecksum(sum, pIpStack->pUDPHdr, sizeof(UDPHDR));

        // must do the size twice because we have this in the psuedo header as well
        sum = CalculateChecksum(sum, &pIpStack->pUDPHdr->cbHdrData, sizeof(pIpStack->pUDPHdr->cbHdrData));
    }
    else
    {
        sum = CalculateChecksum(sum, pIpStack->pUDPHdr, sizeof(UDPHDR));

        // must do the size twice because we have this in the psuedo header as well
        sum = CalculateChecksum(sum, &pIpStack->pUDPHdr->cbHdrData, sizeof(pIpStack->pUDPHdr->cbHdrData));

        // switch order
        ExEndian(&pIpStack->pUDPHdr->portSrc, sizeof(pIpStack->pUDPHdr->portSrc));
        ExEndian(&pIpStack->pUDPHdr->portDest, sizeof(pIpStack->pUDPHdr->portDest));
        ExEndian(&pIpStack->pUDPHdr->cbHdrData, sizeof(pIpStack->pUDPHdr->cbHdrData));
    }

    // add the data
    pIpStack->pUDPHdr->checksum = CalculateChecksum(sum, pIpStack->pPayload, pIpStack->cbPayload);

    // RFC 768, if zero and outgoing, make all FFs
    if(fStartsInMachineOrder)
    {
        if(pIpStack->pUDPHdr->checksum == 0)
        {
            pIpStack->pUDPHdr->checksum = 0xFFFF;
        }
    }
    else if(pIpStack->pUDPHdr->checksum != 0)
    {
        return(ipsIpStackChecksumError);
    }

    return(ipsSuccess);
}
Пример #6
0
static bool ExTCPOptions(TCPHDR * pTCPHdr)
{
    uint32_t    cbOptions = pTCPHdr->dataOffset * sizeof(uint32_t) - sizeof(TCPHDR);
    TCPOPTION * pOptions = (TCPOPTION *) (pTCPHdr + 1);

    if(pTCPHdr->dataOffset == (sizeof(TCPHDR) / sizeof(uint32_t)))
    {
        return(true);
    }
    else if(pTCPHdr->dataOffset < (sizeof(TCPHDR) / sizeof(uint32_t)))
    {
        return(false);
    }

    // run the options
    while(cbOptions > 0)
    {

        // if this is
        switch(pOptions->optionKind)
        {
            case tcpOpKdEndOfList:
                return(true);
                break;
                
            case tcpOpKdNoOperation:
                
                cbOptions--;
                pOptions = (TCPOPTION *) (((void *) pOptions) + 1);
                
                // there is no length, so just go to the next option
                continue;
                break;
                
            default:
                break;
        }

        // check the size to
        if(pOptions->length > cbOptions)
        {
            return(false);
        }

        switch(pOptions->optionKind)
        {
            case tcpOpKdMaxSegSize:
                ExEndian(pOptions->rgu16, sizeof(uint16_t));
                break;

            case tcpOpKdSAckMult:
            case tcpOpKdTimestamp:
                {
                    uint32_t i = 0;
                    uint32_t j = (pOptions->length-2) / sizeof(uint32_t);

                    for(i=0; i<j; i++)
                    {
                        ExEndian(&pOptions->rgu16[2*i], sizeof(uint32_t));
                    }
                }
                break;

            case tcpOpKdWindowScale:
            case tcpOpKdSAck:
            case tcpOpKdAltChksumReq:
            case tcpOpKdAltChksumData:
            default:
                break;
        }

        // go to the next option
        cbOptions -= pOptions->length;
        pOptions = (TCPOPTION *) (((void *) pOptions) + pOptions->length);
    }

    return(true);
}
Пример #7
0
uint32_t ExTCPHeader(IPSTACK * pIpStack, bool fStartsInMachineOrder)
{
    uint16_t sum    = ~(ippnTCP << 8);
    uint16_t cbT    = pIpStack->cbTranportHeader + pIpStack->cbPayload;

    // checksum of the psuedo header
    // remember dataOffset is a byte, so we don't care if in machine or  network order
    ExEndian(&cbT, sizeof(cbT));
    sum = CalculateChecksum(sum, &cbT, sizeof(cbT));
    if(ILIsIPv6(pIpStack->pLLAdp))
    {
        sum = CalculateChecksum(sum, &pIpStack->pIPv6Hdr->ipSrc, sizeof(IPv6));
        sum = CalculateChecksum(sum, &pIpStack->pIPv6Hdr->ipDest, sizeof(IPv6));
    }
    else
    {
        sum = CalculateChecksum(sum, &pIpStack->pIPv4Hdr->ipSrc, sizeof(IPv4));
        sum = CalculateChecksum(sum, &pIpStack->pIPv4Hdr->ipDest, sizeof(IPv4));
    }

    // must put in network order, and do checksum
    if(fStartsInMachineOrder)
    {
        if(!ExTCPOptions(pIpStack->pTCPHdr))
        {
            return(ipsIpStackParsingError);
        }

        pIpStack->pTCPHdr->checksum = 0;    // set this to zero for calcluation
        ExEndian(&pIpStack->pTCPHdr->portSrc, sizeof(pIpStack->pTCPHdr->portSrc));
        ExEndian(&pIpStack->pTCPHdr->portDest, sizeof(pIpStack->pTCPHdr->portDest));

        ExEndian(&pIpStack->pTCPHdr->seqNbr, sizeof(pIpStack->pTCPHdr->seqNbr));
        ExEndian(&pIpStack->pTCPHdr->ackNbr, sizeof(pIpStack->pTCPHdr->ackNbr));

        ExEndian(&pIpStack->pTCPHdr->window, sizeof(pIpStack->pTCPHdr->window));
        ExEndian(&pIpStack->pTCPHdr->urgentPtr, sizeof(pIpStack->pTCPHdr->urgentPtr));

        sum = CalculateChecksum(sum, pIpStack->pTCPHdr, pIpStack->cbTranportHeader);
    }

    else
    {
        sum = CalculateChecksum(sum, pIpStack->pTCPHdr, pIpStack->cbTranportHeader);

        // switch order
        ExEndian(&pIpStack->pTCPHdr->portSrc, sizeof(pIpStack->pTCPHdr->portSrc));
        ExEndian(&pIpStack->pTCPHdr->portDest, sizeof(pIpStack->pTCPHdr->portDest));

        ExEndian(&pIpStack->pTCPHdr->seqNbr, sizeof(pIpStack->pTCPHdr->seqNbr));
        ExEndian(&pIpStack->pTCPHdr->ackNbr, sizeof(pIpStack->pTCPHdr->ackNbr));

        ExEndian(&pIpStack->pTCPHdr->window, sizeof(pIpStack->pTCPHdr->window));
        ExEndian(&pIpStack->pTCPHdr->urgentPtr, sizeof(pIpStack->pTCPHdr->urgentPtr));

        if(!ExTCPOptions(pIpStack->pTCPHdr))
        {
            return(ipsIpStackParsingError);
        }
    }

    // add the data
    pIpStack->pTCPHdr->checksum = CalculateChecksum(sum, pIpStack->pPayload, pIpStack->cbPayload);

    // RFC 768, if zero and outgoing, make all FFs
    if(fStartsInMachineOrder)
    {
        if(pIpStack->pTCPHdr->checksum == 0)
        {
            pIpStack->pTCPHdr->checksum = 0xFFFF;
        }
    }
    else if(pIpStack->pTCPHdr->checksum != 0)
    {
            return(ipsIpStackChecksumError);
    }

    return(ipsSuccess);
}
Пример #8
0
// this puts to order and fills in all of the stack pointers
// payload must at least point to the frame
// or it must already be parsed, it can just change order
bool IPSParseToOrder(IPSTACK * pIpStack, uint32_t Order)
{
    uint32_t        state               = ipsIpStackNotParsed;
    const bool      fInMachineOrder     = (pIpStack->headerOrder == MACHINE_ORDER);
    const bool      fSwitchingOrder     = (pIpStack->headerOrder != Order);
    bool            fInMachineOrderT    = fInMachineOrder;
    uint16_t        cbT                 = 0;
    uint16_t        etpnT               = 0;
     
    // see if we are already done.
    if(pIpStack->fFrameIsParsed && !fSwitchingOrder)
    {
        return(true);
    }

    while(state != ipsSuccess)
    {
        switch(state)
        {

            // in the first state we must get the frame info
            case ipsIpStackNotParsed:

                fInMachineOrderT = fInMachineOrder;

                // if parsed, just get our size
                if(pIpStack->fFrameIsParsed)
                {
                    cbT = pIpStack->cbFrame;
                }

                // if not parsed, what we are parsing is in the payload pointer
                else
                {
                    pIpStack->pFrameII  = (ETHERNETII_FRAME *) pIpStack->pPayload;
                    cbT = pIpStack->cbPayload;
                }

                // if we are switching order
                if(fSwitchingOrder)
                {
                    cbT = ExEthernetFrameHeader(pIpStack->pFrameII, cbT, fInMachineOrderT);
                    fInMachineOrderT = !fInMachineOrder;
                }

                if(cbT < sizeof(ETHERNETII_FRAME))
                {
                    state = ipsIpStackParsingError;
                    break;
                }

                pIpStack->etherType = pIpStack->pFrameII->etherType;
                if(!fInMachineOrderT)
                {
                    ExEndian(&pIpStack->etherType, sizeof(ETHERTYPE));
                }
                
                pIpStack->fIEEE802Frame = IsIEEE802(pIpStack->etherType);
                if(pIpStack->fIEEE802Frame)
                {
                    if(cbT < sizeof(ETHERNET_802_FRAME))
                    {
                        state = ipsIpStackParsingError;
                        break;
                    }

                    pIpStack->etherType = pIpStack->pFrame802->snap.etherType;
                    if(!fInMachineOrderT)
                    {
                        ExEndian(&pIpStack->etherType, sizeof(ETHERTYPE));
                    }
                    pIpStack->cbFrame = sizeof(ETHERNET_802_FRAME);
                }
                else
                {
                    pIpStack->cbFrame = sizeof(ETHERNETII_FRAME);
                }
    
                // update payload and state
                if(!pIpStack->fFrameIsParsed)
                {
                    pIpStack->pPayload  += pIpStack->cbFrame;
                    pIpStack->cbPayload -= pIpStack->cbFrame;
                }

                // go to the next state
                state = pIpStack->etherType;    
                break;
    
            case ethertypeIPv4:

                // if parsed, just get our size
                if(pIpStack->fFrameIsParsed)
                {
                    cbT = pIpStack->cbIPHeader;
                }

                // if not parsed, what we are parsing is in the payload pointer
                else
                {
                    pIpStack->pIPv4Hdr  = (IPv4HDR *) pIpStack->pPayload;
                    cbT = pIpStack->cbPayload;
                }

                if(cbT < sizeof(IPv4HDR))
                {
                    state = ipsIpStackParsingError;
                    break;
                }

                // no Endian to worry on this one, it is only a byte long
                pIpStack->cbIPHeader = pIpStack->pIPv4Hdr->cdwHeader * sizeof(uint32_t);

                if(pIpStack->cbIPHeader > cbT)
                {
                    state = ipsIpStackParsingError;
                    break;
                }

                if(!pIpStack->fFrameIsParsed)
                {
                    uint16_t cbTotal = pIpStack->pIPv4Hdr->cbTotal;

                    pIpStack->protocol = pIpStack->pIPv4Hdr->protocol;
                    if(!fInMachineOrder)
                    {
                       ExEndian(&cbTotal, sizeof(uint16_t));
                    }

                    if(cbTotal > pIpStack->cbPayload)
                    {
                        state = ipsIpStackParsingError;
                        break;
                    }

                    pIpStack->pPayload      += pIpStack->cbIPHeader;

                    // this is very important, we must truncate junk at the end of the payload
                    // cbTotal MUST come from what is specified in the header, and cbPayload MUST
                    // represent the value that cbTotal defines (less the IP header as that is part of cbTotal).
                    // this MUST be an "=" calculation NOT a -= cbIPHeader!
                    pIpStack->cbPayload     = cbTotal - pIpStack->cbIPHeader;
                }
 
                if(fSwitchingOrder)
                {
                    cbT = ExILIPv4Header(pIpStack->pIPv4Hdr, pIpStack->cbIPHeader, fInMachineOrder);
                    
                    // if we are coming from network order
                    // and switching to machine order
                    // and the checksum is not zero, we had a checksum error
                    // that will be the only error that will cause cbT != sizeof(IPv4HDR)
                    if(cbT != sizeof(IPv4HDR))
                    {
                        state = ipsIpStackChecksumError;
                        break;
                    }
                }

                state = pIpStack->protocol;
                break;   

            case ippnUDP:
                state = ipsSuccess;
                
                // parse out the UDP header
                if(!pIpStack->fFrameIsParsed)
                {
                    pIpStack->pUDPHdr  = (UDPHDR *) pIpStack->pPayload;
                    pIpStack->cbTranportHeader = sizeof(UDPHDR);
                    cbT = pIpStack->pUDPHdr->cbHdrData;
                    if(!fInMachineOrder)
                    {
                        ExEndian(&cbT, sizeof(cbT));  
                    }

                    if(cbT < pIpStack->cbPayload)
                    {
                        state = ipsIpStackParsingError;
                        break;
                    }
                    pIpStack->pPayload += sizeof(UDPHDR);
                    pIpStack->cbPayload = cbT - sizeof(UDPHDR);
                }

                // put in proper order and calculate the checksum
                if(fSwitchingOrder)
                {
                    state = ExUDPHeader(pIpStack, fInMachineOrder);
                }
                break;

            case ippnTCP:
                state = ipsSuccess;

                // parse out the TCP header
                if(!pIpStack->fFrameIsParsed)
                {
                    pIpStack->pTCPHdr  = (TCPHDR *) pIpStack->pPayload;
                    pIpStack->cbTranportHeader = pIpStack->pTCPHdr->dataOffset * sizeof(uint32_t);

                    if(pIpStack->cbTranportHeader > pIpStack->cbPayload)
                    {
                        state = ipsIpStackParsingError;
                        break;
                    }
                    pIpStack->pPayload += pIpStack->cbTranportHeader;
                    pIpStack->cbPayload -= pIpStack->cbTranportHeader;
                }

                // put in proper order and calculate the checksum
                if(fSwitchingOrder)
                {
                    state = ExTCPHeader(pIpStack, fInMachineOrder);
                }
                break;

            case ippnICMP:
                if(fSwitchingOrder)
                {
                    cbT =  ExICMP(pIpStack->pPayload, pIpStack->cbPayload, fInMachineOrder);
                    if(cbT != pIpStack->cbPayload)
                    {
                        state = ipsIpStackParsingError;
                        break;
                    }

                    // see if we got a checksum error
                    // because this is the payload, do not make it a hard error
                    if(!fInMachineOrder && pIpStack->pICMPHdr->checksum != 0)
                    {
                        pIpStack->ipss = ipssChecksumError;
                    }
                }
                state = ipsSuccess;
                break;

            case ethertypeARP:
 
                // unfortunately the adaptor may give me a bigger buffer than I think I need.
                if(pIpStack->cbPayload < sizeof(ARPIPv4))
                {
                    state = ipsIpStackParsingError;
                    break;
                }

                etpnT = pIpStack->pARPIPv4->etherType;
                if(!fInMachineOrder)
                {
                    ExEndian(&etpnT, sizeof(etpnT));
                }

                if(etpnT != ethertypeIPv4)
                {
                    state = ipsIpStackNotSupportedPkt;
                    break;
                }

                // get the payload set to the correct size as the adaptor may give us too many bytes with junk at the end
                pIpStack->cbPayload = sizeof(ARPIPv4);
                cbT = sizeof(ARPIPv4);
                if(fSwitchingOrder)
                {
                    cbT = ExARPDatagram(pIpStack->pARPIPv4, pIpStack->cbPayload, fInMachineOrder);
                }

                if(cbT == sizeof(ARPIPv4))
                {
                     state = ipsSuccess;
                }
                else
                {
                   state = ipsIpStackParsingError;
                }
                break;

            case ipsIpStackChecksumError:
                pIpStack->ipss = ipssChecksumError;
                pIpStack->fFrameIsParsed = false;
                return(false);
                break;

            case ipsIpStackParsingError:
                pIpStack->ipss = ipssCorruptPkt;
                pIpStack->fFrameIsParsed = false;
                return(false);
                break;
 
            case ethertypeIPv6:                 // TODO
            case ipsIpStackNotSupportedPkt:
            default:
                pIpStack->ipss = ipssNotSupported;
                pIpStack->fFrameIsParsed = false;
                return(false);
                break;
        }
    }

    if(fSwitchingOrder)
    {
        pIpStack->headerOrder = ~pIpStack->headerOrder;
    }   
    pIpStack->fFrameIsParsed = true;
    return(true);
}