コード例 #1
0
ファイル: DNS.c プロジェクト: Digilent/vivado-library
bool DNSGetNS(const LLADP * pLLAdp, uint32_t index, void * pIPvX)
{
    if(pLLAdp->pDNSMem != NULL && pIPvX != NULL && index < pLLAdp->pDNSMem->dnsNSMax)
    {
        memcpy(pIPvX, &pLLAdp->pDNSMem->dnsNS[index], ILIPSize(pLLAdp));
        return(true);
    }
    return(false);
}
コード例 #2
0
ファイル: TCP.c プロジェクト: Digilent/vivado-library
bool TCPIsInUse(const LLADP * pLLAdp, uint32_t portPair, const void * pIPvXDest)
{
    TCPSOCKET *     pSocket         = NULL;
    bool            fListenIP       = (memcmp(pIPvXDest, &IPListen, ILIPSize(pLLAdp)) == 0);

    while((pSocket = (TCPSOCKET*)FFNext(&g_ffptActiveTCPSockets, pSocket)) != NULL)
    {
        // check to see if this port pair is in active use along with the remote IP
        if(  portPair == pSocket->s.portPair            &&
            (memcmp(pIPvXDest, (void *) &pSocket->s.ipRemote, ILIPSize(pLLAdp)) == 0) )
        {
            // if this totally in use and a duplicate should not be put on the stack
            // however let there be mult listens but check that what we are listining on is the listing IP, not some specific target IP we are waiting for.
            if(pSocket->tcpState > tcpListen || (pSocket->tcpState == tcpListen && !fListenIP))
            {
                return(true);
            }
        }
    }

    return(false);
}
コード例 #3
0
ファイル: TCP.c プロジェクト: Digilent/vivado-library
// this will free the socket if it can't open it
TCPSOCKET * TCPInitSocket(const LLADP * pLLAdp, TCPSOCKET * pSocketOpen, HPMGR hPMGR, const void * pIPvXDest, uint16_t portRemote, uint16_t portLocal, IPSTATUS * pStatus)
{
    IPSTATUS    status          = ipsSuccess;
    SMGR *      pSMGR           = NULL;
    uint32_t    cb              = 0;
    uint32_t    cPages          = 0;

    if(pSocketOpen == NULL)
    {
        AssignStatusSafely(pStatus, ipsSocketNULL);
        return(NULL);
    }
    else if(hPMGR == NULL)
    {
        AssignStatusSafely(pStatus, ipsNoPMGRGiven);
    }

    // find a port
    if(portLocal == portDynamicallyAssign)
    {
        portLocal = GetEphemeralPort(&g_ffptActiveTCPSockets, &g_nextTCPEphemeralPort);
    }

    // get the sequence number
    // we have to get this BEFORE we memset the socket
    // as the timewait may be the socket we are clearing.
    // also, if we are listening, we can only assign the sequence number
    // when we now our remote port and IP as to not duplicate and to watch seq numbers.
    if(portRemote != portListen)
    {
        SKTPORTPAIR portPair;    // remote, local
        portPair.portRemote =   portRemote;
        portPair.portLocal  =   portLocal;

        // worry about the 2MSL timewait issue, get an appropriate sequence number
        if(TCPIsInUse(pLLAdp, portPair.portPair, pIPvXDest))
        {
            AssignStatusSafely(pStatus, ipsPortPairAndIPAlreadyActive);
            return(NULL);
        }
    }

    // build the stream manager to point to the page handler
    // first build the stream to the RxStream and TxStream
    // Rx is the 1st
    pSocketOpen->hPMGR = hPMGR;
    
    // calculate the size of the 2 embedded streams and how to partition the socket stream, stream
    // the Rx is the first indirect stream follwed by the Tx indirect stream in the socket stream
    cb                      = (1 << ((PMGR *) hPMGR)->pf2PerPage);
    cPages                  = ((PMGR *) hPMGR)->cPages;
    pSocketOpen->cbRxSMGR   = GetSMGRSize(min(((cTCPRXPages * cb) - sizeof(SMGR)), cPages));
    pSocketOpen->cbTxSMGR   = GetSMGRSize(min(((cTCPTXPages * cb) - sizeof(SMGR)), cPages));
    cb                      = pSocketOpen->cbRxSMGR + pSocketOpen->cbTxSMGR;

    if(SMGRInit(&pSocketOpen->smgrRxTxBuff, cbMAXTCPSreamRecord, hPMGR) != (HSMGR) &pSocketOpen->smgrRxTxBuff)
    {
        status = ispOutOfMemory;
    }
    else if((pSMGR = (SMGR*)alloca(cb)) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRInit(pSMGR, pSocketOpen->cbRxSMGR, hPMGR) == NULL || SMGRInit((SMGR *) (((uint8_t *) pSMGR) + pSocketOpen->cbRxSMGR), pSocketOpen->cbTxSMGR, hPMGR) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRWrite(&pSocketOpen->smgrRxTxBuff, 0, pSMGR, cb) != cb)
    {
        status = ispOutOfMemory;
    }

    AssignStatusSafely(pStatus, status);
    if(IsIPStatusAnError(status))
    {
        SMGRFree((HSMGR) pSMGR);
        SMGRFree((HSMGR) (((uint8_t *) pSMGR) + pSocketOpen->cbRxSMGR));
        SMGRFree((HSMGR) &pSocketOpen->smgrRxTxBuff);
        IPSReleaseSocket(pSocketOpen);
        return(NULL);
    }

    // make the socket
    pSocketOpen->tcpState       = tcpAllocated;
    pSocketOpen->s.portLocal    = portLocal;
    pSocketOpen->s.portRemote   = portRemote;
    pSocketOpen->s.pLLAdp       = pLLAdp;
    memcpy(&pSocketOpen->s.ipRemote, pIPvXDest, ILIPSize(pLLAdp));

    // get a new seq nbr
    pSocketOpen->sndISS = TCPGetSeqNumber(pLLAdp);

    // max I will allow to come in. RFC 1122 4.2.2.6
    pSocketOpen->cbLocalMSS     = min((PMGRMaxAlloc(hPMGR) >> 2), (uint16_t) (LLGetMTUR(pLLAdp) - 20));

    // Jacobson rule
    pSocketOpen->RTTsa          = RTTsaINIT;
    pSocketOpen->RTTsv          = RTTsvINIT;
    pSocketOpen->tRTO_SET       = RTO(pSocketOpen);
    pSocketOpen->tRTOCur        = pSocketOpen->tRTO_SET;

    return(pSocketOpen);
}
コード例 #4
0
ファイル: DNS.c プロジェクト: Digilent/vivado-library
// 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;
    }
}
コード例 #5
0
ファイル: UDP.c プロジェクト: 757Nauman/chipKIT32-MAX
HSOCKET UDPOpenWithSocket(const LLADP * pLLAdp, UDPSOCKET * pSocket, HPMGR hPMGR, const void * pIPvXDest, uint16_t portRemote, uint16_t portLocal, IPSTATUS * pStatus)
{
//    uint32_t    portPair    = 0;
    IPSTATUS    status      = ipsSuccess;
    SMGR *      pSMGR       = NULL;
    uint32_t    cb          = 0;

    if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }
    else if(pSocket == NULL)
    {
        status = ipsSocketNULL;
    }
    else if(hPMGR == NULL)
    {
        status = ipsNoPMGRGiven;
    }
    else if(pIPvXDest == NULL)
    {
        status = ipsIPAddressIsNull;
    }
    // get the local port
    else if(portLocal == portDynamicallyAssign)
    {
        portLocal = GetEphemeralPort(&g_ffptListeningUDPSockets, &g_nextUDPEphemeralPort);
    }

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

    // build the stream manager to point to the page handler
    // first build the stream to the RxStream
    pSocket->hPMGR = hPMGR;
    if(SMGRInit(&pSocket->smgrRxBuff, cbMAXUDPSreamRecord, hPMGR) != (HSMGR) &pSocket->smgrRxBuff)
    {
        status = ispOutOfMemory;
    }
    else if((pSMGR = alloca((cb = GetSMGRSize(((PMGR *) hPMGR)->cPages)))) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRInit(pSMGR, cb, hPMGR) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRWrite(&pSocket->smgrRxBuff, 0, pSMGR, cb) != cb)
    {
        status = ispOutOfMemory;
    }

    AssignStatusSafely(pStatus, status);
    if(IsIPStatusAnError(status))
    {
        SMGRFree((HSMGR) pSMGR);
        SMGRFree((HSMGR) &pSocket->smgrRxBuff);
        return(NULL);
    }

    pSocket->s.pLLAdp         = pLLAdp;
    pSocket->s.portRemote     = portRemote;
    pSocket->s.portLocal      = portLocal;

    memcpy(&pSocket->s.ipRemote, pIPvXDest, ILIPSize(pLLAdp));

    pSocket->cbRxSMGR       = cb;

    // put on the listening list.
    FFInPacket(&g_ffptListeningUDPSockets, pSocket);

    // return the socket
    return(pSocket);
}