Example #1
0
/*
** tcp6_set_version - sets version for TCP.    
**
** Check to see if driver being restricted to IPv4 or IPv6 only.
** Default is both IPv4(AF_INET) + IPv6(AF_INET6)
**
** VERSION -> meaning . . .
**  ALL or unspecified -> (default) Use both IPv4 and IPv6 addresses
**                        with new (IPv6-enabled) driver
**    4    -> Use old IPv4-only driver (ie, back off to old driver)
**   46    -> Use only IPv4 addresses with new (IPv6-enabled) driver
**    6    -> Use only IPv6 addresses with new (IPv6-enabled) driver
**
*/
static int
tcp6_set_version()
{
	char	*p;
	if( tcpip_version == -1 )  /* Only do 1st time in for performance */
	{
	    TCP_TRACE(2)("tcp6_set_version: entered first time\n");
	    tcpip_version = 0;
	    NMgtAt( "II_TCPIP_VERSION", &p );
	    if ( !(p && *p) && PMget("!.tcp_ip.version", &p) != OK )
                ip_family = AF_UNSPEC;
	    else if (STbcompare(p, 0, "ALL", 0, TRUE) == 0)
                ip_family = AF_UNSPEC;
	    else
	    {
	        tcpip_version = atoi(p);     /* 4*=IPv4 or 6=IPv6 */
	        if ((tcpip_version == 4) || (tcpip_version == 46))
	            ip_family = AF_INET;
	        else if (tcpip_version == 6)
	            ip_family = AF_INET6;
	        else
		{
		    TCP_TRACE(2)("tcp6_set_version: failed! II_TCPIP_VERSION=%s\n", p);
	            return(FAIL);
		}
	    }
	    TCP_TRACE(2)("tcp6_set_version: exiting version=%d, family=%d\n",
		tcpip_version, ip_family);
	} /* end if first time */
	return(OK);
}
Example #2
0
/**
 * @ingroup tcp
 *
 * Processes an incoming packet for a TCP connection in the SYNSENT state.
 * Function based on RFC 763, pg 66-68.
 * @param pkt incoming packet
 * @param tcbptr pointer to transmission control block for connection
 * @return OK or TCP_ERR_SNDRST
 * @pre-condition TCB mutex is already held
 */
int tcpRecvSynsent(struct packet *pkt, struct tcb *tcbptr)
{
    struct tcpPkt *tcp;
    bool ackAccept = FALSE;

    /* Setup packet pointers */
    tcp = (struct tcpPkt *)pkt->curr;

    /* Process ACK */
    if (tcp->control & TCP_CTRL_ACK)
    {
        TCP_TRACE("ACK");
        /* If ACK is unacceptable send reset */
        if (seqlte(tcp->acknum, tcbptr->iss)
            || seqlt(tcbptr->sndnxt, tcp->acknum))
        {
            if (!(tcp->control & TCP_CTRL_RST))
            {
                tcbptr->sndflg |= TCP_FLG_SNDRST;
                return OK;
            }
            return OK;
        }

        /* Check if ACK is acceptable */
        if (seqlte(tcbptr->snduna, tcp->acknum)
            && seqlte(tcp->acknum, tcbptr->sndnxt))
        {
            ackAccept = TRUE;
        }
    }

    /* Process RST */
    if (tcp->control & TCP_CTRL_RST)
    {
        TCP_TRACE("RST");
        if (ackAccept)
        {
            /* ERROR: Connection reset */
            return TCP_ERR_RESET;
        }
        return OK;
    }

    /* Process SYN */
    if (tcp->control & TCP_CTRL_SYN)
    {
        TCP_TRACE("SYN");
        tcbptr->sndwnd = tcp->window;
        tcbptr->sndwl1 = tcp->seqnum;
        tcbptr->rcvnxt = seqadd(tcp->seqnum, 1);
        tcbptr->rcvwnd = seqadd(tcp->seqnum, TCP_INIT_WND);
        tcbptr->rcvflg |= TCP_FLG_SYN;
        tcbptr->sndflg |= TCP_FLG_SNDACK;
        if (ackAccept)
        {
            tcbptr->snduna = tcp->acknum;
            tcbptr->sndwl2 = tcp->acknum;
        }

        /* Remove any segments from retransmission queue which are ACKed */
        tcbptr->rxtcount = 0;
        tcpTimerPurge(tcbptr, TCP_EVT_RXT);
        /* If unacknowledged data remains, reschedule retransmit timer */
        if (seqlt(tcbptr->snduna, tcbptr->sndnxt))
        {
            tcpTimerSched(tcbptr->rxttime, tcbptr, TCP_EVT_RXT);
        }

        if (seqlt(tcbptr->iss, tcbptr->snduna))
        {
            tcbptr->state = TCP_ESTAB;
            signal(tcbptr->openclose);  /* Signal connection open */
            tcbptr->sndflg |= TCP_FLG_SNDDATA;
            return tcpRecvData(pkt, tcbptr);
        }
        else
        {
            tcbptr->state = TCP_SYNRECV;
            /* This send is like a retransmission */
            tcpSend(tcbptr, TCP_CTRL_SYN | TCP_CTRL_ACK,
                    tcbptr->iss, tcbptr->rcvnxt, NULL, 1);
            return tcpRecvData(pkt, tcbptr);
        }
    }

    return OK;
}
Example #3
0
/**
 * Associate a tcp with a network device.
 * @param devptr tcp device table entry
 * @param ap 2nd argument is the local IP address
 *           3rd argument is the remote IP address
 *           4th argument is the local port (auto-assigned if zero)
 *           5th argument is the remote port (ignored if zero)
 *           6th argument is the mode (TCP_ACTIVE or TCP_PASSIVE)
 * @return OK if TCP is opened properly, otherwise SYSERR
 */
devcall tcpOpen(device *devptr, va_list ap)
{
    struct tcb *tcbptr = NULL;
    uchar mode;
    ushort localpt;
    struct netaddr *localip;
    ushort remotept;
    struct netaddr *remoteip;

    /* Setup pointer to tcp */
    tcbptr = &tcptab[devptr->minor];

    wait(tcbptr->mutex);

    /* Mark as allocated */
    tcbptr->devstate = TCP_ALLOC;

    /* Verify device is not already open */
    if ((tcbptr->state != TCP_CLOSED) && (tcbptr->state != TCP_LISTEN))
    {
        signal(tcbptr->mutex);
        TCP_TRACE("Already open");
        return SYSERR;
    }

    /* Obtain remaining arguments */
    localip = (struct netaddr *)va_arg(ap, uint);
    remoteip = (struct netaddr *)va_arg(ap, uint);
    localpt = va_arg(ap, uint);
    remotept = va_arg(ap, uint);
    mode = va_arg(ap, uint);

    /* Verify local IP is specified */
    if (NULL == localip)
    {
        tcbptr->devstate = TCP_FREE;
        signal(tcbptr->mutex);
        TCP_TRACE("Invalid args");
        return SYSERR;
    }

    /* Allocate a local port if none is specified */
    if (NULL == localpt)
    {
        localpt = allocPort();
    }

    /* Mutually link tcp record with device table entry */
    tcbptr->dev = devptr->num;

    /* Initialize port and ip fields */
    tcbptr->localpt = localpt;
    netaddrcpy(&tcbptr->localip, localip);
    tcbptr->remotept = remotept;
    if (NULL == remoteip)
    {
        tcbptr->remoteip.type = NULL;
    }
    else
    {
        netaddrcpy(&tcbptr->remoteip, remoteip);
    }
    tcbptr->opentype = mode;

    /* Setup transmission control block */
    if (SYSERR == tcpSetup(tcbptr))
    {
        tcpFree(tcbptr);
        TCP_TRACE("Failed to setup TCB");
        return SYSERR;
    }

    /* Perform appropriate action and change state */
    switch (mode)
    {
    case TCP_PASSIVE:
        tcbptr->state = TCP_LISTEN;
        break;
    case TCP_ACTIVE:
        if (SYSERR == tcpOpenActive(tcbptr))
        {
            tcpFree(tcbptr);
            TCP_TRACE("Failed to active open");
            return SYSERR;
        }
        break;
    default:
        tcpFree(tcbptr);
        TCP_TRACE("Unknown mode");
        return SYSERR;
    }

    signal(tcbptr->mutex);

    TCP_TRACE("Waiting for other side");
    wait(tcbptr->openclose);    /* Wait for connection open */
    TCP_TRACE("Opened connection");
    return OK;
}