Example #1
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);
}
Example #2
0
// does not calculate checksum; this is calculated when we got to network order
static bool IPSSetHeader(IPSTACK * pIpStack, IPSTATUS * pStatus)
{
    if(ILIsIPv6(pIpStack->pLLAdp))
    {
        memset(pIpStack->pIPv6Hdr, 0, sizeof(IPv6HDR));
        AssignStatusSafely(pStatus, ipsIpStackNotSupportedPkt);
        return(false);
    }
    else
    {
        if(pIpStack->cbIPHeader < sizeof(IPv4HDR))
        {
            AssignStatusSafely(pStatus, ipsInvalidIPv4HedearSize);
            return(false);;
        }

        // Per RFC 791
        pIpStack->cbIPHeader            = sizeof(IPv4HDR);
        pIpStack->pIPv4Hdr->version     = 4;                    
        pIpStack->pIPv4Hdr->cdwHeader   = sizeof(IPv4HDR) / 4;                
        pIpStack->pIPv4Hdr->cbTotal     = sizeof(IPv4HDR) + pIpStack->cbTranportHeader + pIpStack->cbPayload;                
        pIpStack->pIPv4Hdr->ident       = 0; 
        pIpStack->pIPv4Hdr->u16         = 0; 
        pIpStack->pIPv4Hdr->timeToLive  = TIME_TO_LIVE;
        pIpStack->pIPv4Hdr->protocol    = pIpStack->protocol;     // typically ippnICMP, ippnTCP, ippnUDP
        pIpStack->pIPv4Hdr->hdrChecksum = 0;            // for calculations, this is set to 0, RFC 791
        pIpStack->pIPv4Hdr->ipSrc.u32   = pIpStack->pLLAdp->ipMy.ipv4.u32;
        pIpStack->pIPv4Hdr->ipDest.u32  = IPv4BROADCAST.u32; 

        // TODO: Process options
        pIpStack->fOptionPresent        = false;

        return(true);
    }

    AssignStatusSafely(pStatus, ipsIpStackParsingError);
    return(false);
}
Example #3
0
// only called for incoming packets
void TCPProcess(IPSTACK *  pIpStack)
{
    TCPSOCKET *     pSocketCur      = NULL;
    TCPSOCKET *     pSocketListen   = NULL;
    TCPSOCKET *     pSocketExact    = NULL;
    
    // see if this is directed to my IP
    if( !(  // this is not my IP address

        // my IPv4 address
        (!ILIsIPv6(pIpStack->pLLAdp) && pIpStack->pLLAdp->ipMy.ipv4.u32 == pIpStack->pIPv4Hdr->ipDest.u32)
                                    ||
        // my IPv6 addresss
        (memcmp(&pIpStack->pLLAdp->ipMy.ipv6, &pIpStack->pIPv6Hdr->ipDest, sizeof(IPv6)) == 0)     ))
    {
        // just get out if it is not for me
        return;
    }

    // look at all of the sockets
    while((pSocketCur = (TCPSOCKET*)FFNext(&g_ffptActiveTCPSockets, pSocketCur)) != NULL)
    {
        if( pSocketCur->tcpState > tcpListen   &&
            pIpStack->pTCPHdr->portPair == pSocketCur->s.portPair  &&

        // matches the remote IP
        ((!ILIsIPv6(pIpStack->pLLAdp) && pSocketCur->s.ipRemote.ipv4.u32 == pIpStack->pIPv4Hdr->ipSrc.u32)
                                    ||
        (memcmp(&pSocketCur->s.ipRemote.ipv6, &pIpStack->pIPv4Hdr->ipSrc, sizeof(IPv6)) == 0))   )

        {
            pSocketExact = pSocketCur;
            break;
        }
        else if(pSocketCur->tcpState    == tcpListen                    &&
                pSocketCur->s.portLocal == pIpStack->pTCPHdr->portDest  &&
                pIpStack->pTCPHdr->fSyn)
        {
            pSocketListen = pSocketCur;
        }
    }

    // see if we did not find an exact match
    // but we are listening
    if(pSocketExact == NULL)
    {
        pSocketExact = pSocketListen;
    }

    // a match to an active socket
    if(pSocketExact != NULL)
    {
        IPSUpdateARPEntry(pIpStack);
        memcpy(&pSocketExact->s.macRemote, &pIpStack->pFrameII->macSrc, sizeof(MACADDR));
        TCPStateMachine(pIpStack, pSocketExact, NULL);
    }

    // to no socket at all, this will cause a RST to be sent.
    else
    {
        TCPStateMachine(pIpStack, NULL, NULL);
    }
}
Example #4
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);
}
Example #5
0
bool DNSInit(const LLADP * pLLAdp, void * rgbDNSMem, uint32_t cbDNSMem, HPMGR hPMGR, IPSTATUS * pStatus)
{
    IPSTATUS    status = ipsSuccess;
    DNSMEM *    pDNSMem = (DNSMEM *) rgbDNSMem;
    uint32_t    i = 0;

    if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }
    else if(hPMGR == NULL)
    {
        status = ipsNoPMGRGiven;
    }
    else if(rgbDNSMem == NULL)
    {
        status = ipsDNSMemIsNULL;
    }
    else if(cbDNSMem < sizeof(DNSMEM))
    {
        status = ipsDNSNotEnoughMem;
    }
    else if(pLLAdp->pDNSMem != NULL)
    {
        status = ipsDNSAlreadyInitialized;
    }
    else if(ILIsIPv6(pLLAdp))
    {
        status = ipsIPv6NotSupported;
    }

    if(IsIPStatusAnError(status))
    {
        AssignStatusSafely(pStatus, status);
        return(false);
    }

    memset(pDNSMem, 0, cbDNSMem);
    if(&pDNSMem->socket != UDPOpenWithSocket(pLLAdp, &pDNSMem->socket, hPMGR, &IPv4BROADCAST, portDNSServer, portDynamicallyAssign, &status) ||
       IsIPStatusAnError(status))
    {
        UDPClose(&pDNSMem->socket);
        AssignStatusSafely(pStatus, status);
        return(false);
    }

    pDNSMem->dnsNSMax = (cbDNSMem - sizeof(DNSMEM)) / sizeof(IPv4or6);
    pDNSMem->cDhcpNS = 0;
    pDNSMem->iDNSCur = DNSiInvalid;
    pDNSMem->iDNSWorks = DNSiInvalid;
    pDNSMem->dnsState = dnsReady;
    pDNSMem->cTry = 0;
    ((LLADP *) pLLAdp)->pDNSMem = pDNSMem;

    // initialize them all to the Google NS
    // that way there is something in all of the slots
    // this will get over written if DHCP is used.
    for(i=0; i<pDNSMem->dnsNSMax; i++)
    {
        if((i % 2) == 0)
        {
            pDNSMem->dnsNS[i].ipv4.u32 = 0x04040808; // Google public DNS server
        }
        else
        {
            pDNSMem->dnsNS[i].ipv4.u32 = 0x08080808; // Google public DNS server
        }
    }

    AssignStatusSafely(pStatus, status);
    return(true);
}
Example #6
0
// Notes on dnsNSMax and cDhcpNS. You would think that we should only cycle through cDhcpNS as this is the number
// DNS servers given to us by DHCP, however, sometimes DHCP does not give us good DNS servers and for the
// SNTP server to work, we need a good DNS server. So we continue to check the default, pre initialized google DNS
// servers after the DHCP DNS servers are checked first. If we get a lot of DNS servers from DHCP, then ultimately
// all of the pre installed google servers will be overwritten in the dnsNSMax list, but if we got a lot of DNS servers
// the assumption is that they are good ones. In particular, I found that Verizon did not give me very good DNS servers, they
// could not resolve the SNTP time servers.
static void DNSStateMachine(const LLADP * pLLAdp)
{
    IPSTATUS    status      = ipsSuccess;

    if(pLLAdp == NULL || pLLAdp->pDNSMem == NULL || !ILIsIPSetup(pLLAdp, NULL))
    {
        return;
    }

    switch(pLLAdp->pDNSMem->dnsState)
    {
        case dnsSend:
            if(pLLAdp->pDNSMem->dnsNSMax == 0)
            {
                pLLAdp->pDNSMem->dnsState = dnsReady;
                pLLAdp->pDNSMem->cTry = 0;
                break;
            }
            else if(pLLAdp->pDNSMem->cTry >= (pLLAdp->pDNSMem->dnsNSMax * DNSMINTRY))
            {
                if(pLLAdp->pDNSMem->iDNSCur == pLLAdp->pDNSMem->iDNSWorks)
                {
                    pLLAdp->pDNSMem->iDNSWorks = DNSiInvalid;
                }
                pLLAdp->pDNSMem->iDNSCur = DNSiInvalid;
                pLLAdp->pDNSMem->dnsState = dnsReady;
                pLLAdp->pDNSMem->cTry = 0;
                break;
            }
            else if(pLLAdp->pDNSMem->iDNSWorks < pLLAdp->pDNSMem->dnsNSMax)
            {
                pLLAdp->pDNSMem->iDNSCur = pLLAdp->pDNSMem->iDNSWorks;
            }
            else if(pLLAdp->pDNSMem->iDNSCur >= pLLAdp->pDNSMem->dnsNSMax)
            {
                pLLAdp->pDNSMem->iDNSCur = 0;
            }
            else
            {
                pLLAdp->pDNSMem->iDNSCur = (pLLAdp->pDNSMem->iDNSCur + 1) % pLLAdp->pDNSMem->dnsNSMax;
            }

            // set this up for an attempt to get the IP address
            memcpy(&pLLAdp->pDNSMem->socket.s.ipRemote, &pLLAdp->pDNSMem->dnsNS[pLLAdp->pDNSMem->iDNSCur], ILIPSize(pLLAdp));

            // fall thru on success

        case dnsReadySend:

            // clear the current IP address
            memset(&pLLAdp->pDNSMem->ip, 0, sizeof(IPv4or6));

            // just make this unique for this pass
            pLLAdp->pDNSMem->dnsDG.dnsHdr.ID++;

            // set my timers and counts
            pLLAdp->pDNSMem->cTry++;
            pLLAdp->pDNSMem->tTimeout = dnsWaitForRetry;
            pLLAdp->pDNSMem->tStart = SYSGetMilliSecond();

            // send out the DNS datagram
            UDPSend(&pLLAdp->pDNSMem->socket, (uint8_t *) &pLLAdp->pDNSMem->dnsDG, pLLAdp->pDNSMem->cbDNSDG, &status);

            // see if it went out.
            if(IsIPStatusAnError(status))
            {
                pLLAdp->pDNSMem->dnsState = dnsReady;
                pLLAdp->pDNSMem->cTry = 0;
            }
            else
            {
                pLLAdp->pDNSMem->dnsState = dnsWaiting;
            }
            break;

        case dnsWaiting:
            {
                uint16_t cbDG = UDPAvailable(&pLLAdp->pDNSMem->socket) ;
                IPSTATUS status;

                if(cbDG > sizeof(DNSHDR))
                {
                    // we need some space for the datagram
                    uint8_t     rgbDNSDG[DNSMAXUDPSIZE];
                    DNSDG *     pDNSDG  = (DNSDG *) rgbDNSDG;
                    uint8_t *   pEnd    = NULL;
                    uint8_t *   pCName  = NULL;
                    DNSRR *     pDNSRRA = NULL;

                    // read the DNS datagram
                    cbDG = UDPRead(&pLLAdp->pDNSMem->socket, rgbDNSDG, DNSMAXUDPSIZE, &status);

                    // There are some servers setting this and they should not! RFC 6195 2.1 and I need to ignore it
                    // Plus this is used internally to determine if we are in machine or network order. This is in network order right now.
                    pDNSDG->dnsHdr.Z = 0;

                    // now put in machine order.
                    cbDG = ExDNSDG(pDNSDG, cbDG);
                    pEnd = rgbDNSDG + cbDG;
                    
                    // if this is not a my response, keep waiting
                    // remember the ID is not exchanged, so network and machine order will have the same ID
                    if(!pDNSDG->dnsHdr.QR || pDNSDG->dnsHdr.ID != pLLAdp->pDNSMem->dnsDG.dnsHdr.ID)
                    {
                        break;
                    }

                    // ops and error occured, jump to finish with error
                    // go to the error state with no address found
                    if(pDNSDG->dnsHdr.RCODE != DNSRCODENoError)
                    {
                        // this is a failure case; go to the next DNS server
                        pLLAdp->pDNSMem->dnsState = dnsSend;
                        break;
                    }
                    
                    // get the canonical name for what we are looking for
                    // the first record is the question which has the name we used.
                    // we need to use the one in this datagram because we do memory range
                    // checking and if we use the QR we sent, it would be out of the memory range
                    pCName = DNSFindCName(pDNSDG, DNSRRAN, pDNSDG->rrRecords, pEnd);

                    // now find the A record
                    pDNSRRA = DNSFindRR(pDNSDG, NULL, DNSRRAN, DNSTYPEA, DNSCLASSIN, pCName, pEnd);

                    // if we got the A record we are done
                    if( pDNSRRA != NULL                                             &&
                        ((ILIsIPv6(pLLAdp)  &&  pDNSRRA->RDLENGTH == sizeof(IPv6))  ||
                         (!ILIsIPv6(pLLAdp) &&  pDNSRRA->RDLENGTH == sizeof(IPv4))  )   )
                    {
                        // copy in our result
                        memcpy(&pLLAdp->pDNSMem->ip, pDNSRRA->RDATA, pDNSRRA->RDLENGTH);

                        // say we are done
                        pLLAdp->pDNSMem->dnsState = dnsReady;
                        pLLAdp->pDNSMem->cTry = 0;

                        // We got an IP so we know this DNS server can work, remember that
                        if(pLLAdp->pDNSMem->iDNSCur < pLLAdp->pDNSMem->dnsNSMax)
                        {
                            pLLAdp->pDNSMem->iDNSWorks = pLLAdp->pDNSMem->iDNSCur;
                        }

                        // get out we found it and are done.
                        break;
                    }

                    // by default we will go to the next well know sever unless we pick up a better NS to go to
                    pLLAdp->pDNSMem->dnsState = dnsSend;

                    // we did not find anything, so update our DNS request to use the new CName
                    if(pCName != pDNSDG->rrRecords)
                    {
                        // make the new DNS packet with the CName instead of what we were using
                        uint16_t cbMax = DNSCreateIPv4QueryDN(pLLAdp, rgbDNSDG, pCName, pEnd, &pLLAdp->pDNSMem->dnsDG);
                        pLLAdp->pDNSMem->cbDNSDG = ExDNSDG(&pLLAdp->pDNSMem->dnsDG, cbMax);
                    }

                    // Didn't find an A record
                    // But maybe there is a name server we should try.
                    // If we asked for recursion and go it, no sense working the issue ourselves.
                    // likewise if there are now NS with IP addresses, no sense working the issue
                    if(!(pDNSDG->dnsHdr.RD && pDNSDG->dnsHdr.RA) && pDNSDG->dnsHdr.NSCOUNT > 0 && pDNSDG->dnsHdr.ARCOUNT > 0)
                    {
                        // this DNS server gave us something, so remember it
                        if(pLLAdp->pDNSMem->iDNSCur < pLLAdp->pDNSMem->dnsNSMax)
                        {
                            pLLAdp->pDNSMem->iDNSWorks = pLLAdp->pDNSMem->iDNSCur;
                        }

                        pDNSRRA = DNSFindNSARR(pDNSDG, pCName, pEnd, DNSTYPEA);

                        // if this looks like a good IP address to try, lets contact that name server
                        if(pDNSRRA != NULL && pDNSRRA->RDLENGTH == sizeof(IPv4))
                        {
                            // say were are not using one of our well known DNS servers
                            pLLAdp->pDNSMem->iDNSCur = DNSiInvalid;
                            
                            // Put the IP in our socket
                            memcpy(&pLLAdp->pDNSMem->socket.s.ipRemote, pDNSRRA->RDATA, pDNSRRA->RDLENGTH);
                            pLLAdp->pDNSMem->dnsState = dnsReadySend;
                        }
                    }

                    else if(pLLAdp->pDNSMem->iDNSWorks == pLLAdp->pDNSMem->iDNSCur)
                    {
                        pLLAdp->pDNSMem->iDNSWorks = DNSiInvalid;
                    }

                }
                else if((SYSGetMilliSecond() - pLLAdp->pDNSMem->tStart) >= pLLAdp->pDNSMem->tTimeout)
                {
                    pLLAdp->pDNSMem->dnsState = dnsWaitTry;
                }
            }
            break;

        case dnsWaitTry:

            if(pLLAdp->pDNSMem->iDNSWorks == pLLAdp->pDNSMem->iDNSCur)
            {
                pLLAdp->pDNSMem->iDNSWorks = DNSiInvalid;
            }
            
            if((pLLAdp->pDNSMem->cTry % DNSMINTRY) == 0)
            {
                pLLAdp->pDNSMem->dnsState = dnsSend;                
            }
            else
            {
                pLLAdp->pDNSMem->dnsState = dnsReadySend;
            }

            break;

        case dnsReady:
            pLLAdp->pDNSMem->cTry = 0;
            break;

        // noting to do here, either we have something in the DNS memory IP or not.
        case dnsRedirect:
        case dnsUninit:
        default:
            break;
    }
}
Example #7
0
// This is not a URL, this must be a domain nume such as www.foo.bar.com with an optional . at the end.
bool DNSResolve(const LLADP * pLLAdp, uint8_t const * const pchDomainName, uint32_t cchDomanName, void * pIPvX, IPSTATUS * pStatus)
{
    IPSTATUS    status = ipsSuccess;

    // see if we are initialized
    if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }
    else if( !ILIsIPSetup(pLLAdp, &status) )
    {
        // do nothing, I got the status
    }
    else if(pLLAdp->pDNSMem == NULL || pLLAdp->pDNSMem->dnsState == dnsUninit)
    {
        status = ipsDNSIsNotInitialized;
    }
    else if(pchDomainName == NULL)
    {
        status = ipsDomainNameIsNULL;
    }
    else if(pIPvX == NULL)
    {
        status = ipsIPIsNULL;
    }

    // we are currently processing a DNS reqeust
    else if(pLLAdp->pDNSMem->dnsState != dnsReady)
    {
        // this is not the one we are working on!
        if(pLLAdp->pDNSMem->pchDomainName != pchDomainName)
        {
            status = ipsDNSIsInUse;
        }

        // this is the one we are working on, check to see if it is done.
        else
        {
            // go into the state machine.
            status = ipsDNSIsResolving;
        }
    }

    // we are done, see if we got it or not
    else if(pLLAdp->pDNSMem->pchDomainName == pchDomainName && pLLAdp->pDNSMem->cchDomainName == cchDomanName && strncmp((char *) pLLAdp->pDNSMem->pchDomainName, (char *) pchDomainName, cchDomanName) == 0)
    {
        if(ILIsIPv6(pLLAdp))
        {
            // have no idea
            if(memcmp(&pLLAdp->pDNSMem->ip.ipv6, &IPv6NONE, sizeof(IPv6)) == 0)
            {
                status = ipsDNSFailedToResolve;
            }
            // got it
            else
            {
                memcpy(pIPvX, &pLLAdp->pDNSMem->ip.ipv6, sizeof(IPv6));
            }
        }
        // IPv4
        else
        {
            // have no idea
            if(pLLAdp->pDNSMem->ip.ipv4.u32 == IPv4NONE.u32)
            {
                status = ipsDNSFailedToResolve;
            }
            // got it
            else
            {
                memcpy(pIPvX, &pLLAdp->pDNSMem->ip.ipv4, sizeof(IPv4));
            }
        }
    }

    // if we are ready, but he is asking for something else, start a new request.
    // check to see if the domain name starts with a number; as in IP address
    // TODO: IPv6 support
    else if(isdigit(*pchDomainName))
    {
        uint32_t i = 0;
        uint32_t j = 0;
        uint32_t k = 0;
        uint8_t const * pch = pchDomainName;
        
        if(ILIsIPv6(pLLAdp))
        {
            // TODO: do IPv6 support
        }
        else
        {    
            for(i=0; i<4; i++)
            {
                for(j=0, k=0; j<3 && isdigit(*pch); j++, pch++)
                {
                    k *= 10;
                    k += (*pch - '0');                    
                }
                
                if((i<3 && *pch == '.') || (i == 3 && (*pch == '/' || *pch == '\0')))
                {
                    ((IPv4 *) pIPvX)->u8[i] = (uint8_t) k;
                    pch++;
                }

                // if is clearly not an IP address
                // try it as a domain name
                else
                {
                    DNSStartIPv4Request(pLLAdp, pchDomainName, cchDomanName, &status);
                    break;
                }
            }
        
            if(status == ipsSuccess)
            {
                // pretend we got the IP
                pLLAdp->pDNSMem->ip.ipv4.u32 = ((IPv4 *) pIPvX)->u32;
                pLLAdp->pDNSMem->pchDomainName = pchDomainName;
                pLLAdp->pDNSMem->cchDomainName = cchDomanName;
            }
            else
            {
                memcpy(pIPvX, &IPv4NONE, sizeof(IPv4));
            }
        }
    }

    // otherwise we need to go look it up.
    else
    {
        DNSStartIPv4Request(pLLAdp, pchDomainName, cchDomanName, &status);
    }

    AssignStatusSafely(pStatus, status);
    return(status == ipsSuccess);
}
Example #8
0
IPSTACK * IPSInitIpStack(const LLADP * pLLAdp, void * pIpStackBuff, uint32_t type)
{
    IPSTACK * pIpStack = (IPSTACK *) pIpStackBuff;

    // nothing open
    if(pIpStackBuff == NULL)
    {
        return(NULL);
    }

    // take this one
    // build it up to a default IPSTACK with pointers set in
    // we are clearing more than the IPSTACK, we are clearing all of the
    // following space for the headers.
    memset(pIpStackBuff, 0, IPStackEntrySize);

    pIpStack->fFreeIpStackToAdp     = true;

    pIpStack->headerOrder           = MACHINE_ORDER;
    pIpStack->pLLAdp                = pLLAdp;

    pIpStack->pFrameII              = (ETHERNETII_FRAME*)(((void *) pIpStack) + sizeof(IPSTACK));
    pIpStack->cbFrame               = sizeof(ETHERNETII_FRAME);

    pIpStack->pIPHeader             = (((void *) pIpStack->pFrameII) + sizeof(ETHERNETII_FRAME));

    if(ILIsIPv6(pLLAdp))
    {
        pIpStack->etherType         = ethertypeIPv6;
        pIpStack->cbIPHeader        = sizeof(IPv6HDR);
        pIpStack->pTransportHeader  = (pIpStack->pIPHeader + sizeof(IPv6HDR));
    }
    else
    {
        pIpStack->etherType         = ethertypeIPv4;
        pIpStack->cbIPHeader        = sizeof(IPv4HDR);
        pIpStack->pTransportHeader  = (pIpStack->pIPHeader + sizeof(IPv4HDR));
    }

    switch(type)
    {
        case ippnICMP:
            pIpStack->pTransportHeader	= NULL;
            pIpStack->cbTranportHeader 	= 0;
            pIpStack->protocol          = ippnICMP;
            break;

        case ippnTCP:
            pIpStack->cbTranportHeader 	= sizeof(TCPHDR);
            pIpStack->protocol          = ippnTCP;
            break;

        case ippnUDP:
            pIpStack->cbTranportHeader 	= sizeof(UDPHDR);
            pIpStack->protocol          = ippnUDP;
            break;

        case ethertypeARP:
            pIpStack->pTransportHeader	= NULL;
            pIpStack->cbTranportHeader 	= 0;
            pIpStack->pIPHeader         = NULL;
            pIpStack->cbIPHeader        = 0;
            pIpStack->etherType         = ethertypeARP;
            break;

        default:
            return(NULL);
    }

    // put some defaults in
    // from here in, the IPSTACK values could be wrong, but we are putting something in.
    pIpStack->pPayload                  = NULL;
    pIpStack->cbPayload                 = 0;

    // build up the stack and headers with defaults
    // broadcast MAC and IP
    // protocol assumes TCP, but that can be changed later.
    // this should be an assert, it should never fail as this is
    // built from scratch and there should be no errors
    if(!IPSConstructIpStackHeaders(pIpStack, NULL))
    {
        return(NULL);
    }

    return(pIpStack);
}
Example #9
0
void UDPProcess(IPSTACK * pIpStack)
{
    UDPSOCKET *     pSocketCur          = NULL;
    UDPSOCKET *     pSocketListen       = NULL;
    UDPSOCKET *     pSocketAnyRemoteIP  = NULL;
    UDPSOCKET *     pSocketExact        = NULL;
    bool            fBroadcast          = false;
    bool            fMyIP               = ILIsIPv6(pIpStack->pLLAdp) ?
                                            ILIsMyIP(pIpStack->pLLAdp, &pIpStack->pIPv6Hdr->ipDest, &fBroadcast) :
                                            ILIsMyIP(pIpStack->pLLAdp, &pIpStack->pIPv4Hdr->ipDest, &fBroadcast);

    // see if this is directed to my IP
    if( !fMyIP )
    {
        return;
    }

    // look at all listening sockets to see if the ports and remote IP match
    while((pSocketCur = FFNext(&g_ffptListeningUDPSockets, pSocketCur)) != NULL)
    {
        // make sure we have consistant IPs
        if(ILIsIPv6(pSocketCur->s.pLLAdp) == ILIsIPv6(pIpStack->pLLAdp))
        {
            // listening socket, only check local port, remote port/IP will be set
            if( pSocketCur->s.portRemote == portListen &&
                pSocketCur->s.portLocal == pIpStack->pUDPHdr->portDest )
            {
                pSocketListen = pSocketCur;
            }

            // all connected sockets
            else if(pIpStack->pUDPHdr->portPair == pSocketCur->s.portPair)
            {
                // this is an IPv4 address
                if(!ILIsIPv6(pIpStack->pLLAdp))
                {
                    // exact match
                    if(pSocketCur->s.ipRemote.ipv4.u32 == pIpStack->pIPv4Hdr->ipSrc.u32)
                    {
                        pSocketExact = pSocketCur;
                        break;
                    }

                    // this is only supported for DHCP IPv4
                    else if(pSocketCur->s.ipRemote.ipv4.u32 == UDPAnyRemoteIPv4.u32)
                    {
                        pSocketAnyRemoteIP = pSocketCur;
                    }
                }

                // else an IPv6 address
                else
                {
                    // exact match
                    if(memcmp(&pSocketCur->s.ipRemote.ipv6, &pIpStack->pIPv6Hdr->ipSrc, sizeof(IPv6)) == 0)
                    {
                        pSocketExact = pSocketCur;
                        break;
                    }
                }
            }
        }
    }

    // a match to an active socket
    if(pSocketExact == NULL)
    {
        if(pSocketAnyRemoteIP != NULL)
        {
            pSocketExact = pSocketAnyRemoteIP;
        }
        else if(pSocketListen != NULL)
        {
            pSocketExact = pSocketListen;

            pSocketExact->s.portRemote = pIpStack->pUDPHdr->portSrc;

            if(ILIsIPv6(pSocketExact->s.pLLAdp))
            {
                memcpy(&pSocketExact->s.ipRemote.ipv6, &pIpStack->pIPv6Hdr->ipSrc, sizeof(IPv6));
            }
            else
            {
                pSocketExact->s.ipRemote.ipv4.u32 = pIpStack->pIPv4Hdr->ipSrc.u32;
            }
        }
    }

    // no match to anything, get out.
    if(pSocketExact == NULL)
    {
        return;
    }

    // update our ARP table
    IPSUpdateARPEntry(pIpStack);
    memcpy(&pSocketExact->s.macRemote, &pIpStack->pFrameII->macSrc, sizeof(MACADDR));

    // Receive the UDP input data
    UDPProcessRx(pIpStack, pSocketExact);
}
Example #10
0
bool UDPRawSend(const LLADP * pLLAdp, IPSTACK *   pIpStack, const void * pIPvXDest, uint16_t portDest, uint16_t portSrc, const uint8_t * pDatagram, uint32_t cbDatagram, bool fFreeDatagramImmediately, IPSTATUS * pStatus)
{   
    bool        fRet        = false;
    IPSTATUS    status      = ipsSuccess;

    if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }
    else if(pIpStack == NULL)
    {
        status = ipsIpStackNULL;
    }
    else if(pIPvXDest == NULL)
    {
        status = ipsIPAddressIsNull;
    }
    else if(pDatagram == NULL)
    {
        status = ipsUDPNullDatagram;
    }
    
    // sometimes we want to keep the actual buffer we passed in the IpStack
    // because we will later want to reuse it and don't want it copied and freed
    // the downside is, we have to know that the send is complete somehow; typically
    // would do this if you don't reuse the buffer until we get a response from the
    // remote and thus know we must have sent the datagram already.
    // this is typically NOT the way we would use this, but DHCP Does this extensively
    else if(!fFreeDatagramImmediately)
    {
        pIpStack->pPayload = (void *) pDatagram;
    }
    else if(IPSGetPayloadFromAdaptor(pIpStack, cbDatagram) == cbDatagram)
    {
        // this is ugly to have to copy the data but somewhat required
        // the problem is, when we send we may need to wait while an APR is proformed and that
        // will require that the pDatagram be constant, however on return from this funciton
        // the application may immediately reuse the memory to construct the next datagram
        memcpy(pIpStack->pPayload, pDatagram, cbDatagram);
    }
    else
    {
        status = ispOutOfMemory;
    }

    if(IsIPStatusAnError(status))
    {
        AssignStatusSafely(pStatus, status);
        return(false);
    }

    pIpStack->pUDPHdr->portSrc         	= portSrc;
    pIpStack->pUDPHdr->portDest        	= portDest;
    pIpStack->pUDPHdr->cbHdrData       	+= cbDatagram;
    pIpStack->cbPayload               	= cbDatagram;

    if(ILIsIPv6(pLLAdp))
    {
        pIpStack->pIPv6Hdr->cbPayload	= pIpStack->cbPayload;
        memcpy(&pIpStack->pIPv6Hdr->ipDest, pIPvXDest, sizeof(IPv6));
    }
    else
    {
        pIpStack->pIPv4Hdr->cbTotal += pIpStack->cbPayload;
        memcpy(&pIpStack->pIPv4Hdr->ipDest, pIPvXDest, sizeof(IPv4));
    }

    fRet = ILSend(pIpStack, pStatus);

    return(fRet);
}