Exemplo n.º 1
0
void State_ViewAbility::Update()
{
	switch( t.Key() ){
		case 'a':
			s.pop();
			break;
		case 's':
			s.push(NEW_STATE(SwapAbility, m->pos, true));
			break;
	}
}
Exemplo n.º 2
0
int CTCPConnection::Close (void)
{
	if (m_nErrno < 0)
	{
		return m_nErrno;
	}
	
	switch (m_State)
	{
	case TCPStateClosed:
		return -1;

	case TCPStateListen:
	case TCPStateSynSent:
		StopTimer (TCPTimerRetransmission);
		NEW_STATE (TCPStateClosed);
		break;

	case TCPStateSynReceived:
	case TCPStateEstablished:
		assert (!m_bFINQueued);
		m_StateAfterFIN = TCPStateFinWait1;
		m_nRetransmissionCount = MAX_RETRANSMISSIONS;
		m_bFINQueued = TRUE;
		break;
		
	case TCPStateFinWait1:
	case TCPStateFinWait2:
		break;

	case TCPStateCloseWait:
		assert (!m_bFINQueued);
		m_StateAfterFIN = TCPStateLastAck;	// RFC 1122 section 4.2.2.20 (a)
		m_nRetransmissionCount = MAX_RETRANSMISSIONS;
		m_bFINQueued = TRUE;
		break;

	case TCPStateClosing:
	case TCPStateLastAck:
	case TCPStateTimeWait:
		return -1;
	}

	if (m_nErrno < 0)
	{
		return m_nErrno;
	}
	
	return 0;
}
Exemplo n.º 3
0
CTCPConnection::CTCPConnection (CNetConfig	*pNetConfig,
				CNetworkLayer	*pNetworkLayer,
				CIPAddress	&rForeignIP,
				u16		 nForeignPort,
				u16		 nOwnPort)
:	CNetConnection (pNetConfig, pNetworkLayer, rForeignIP, nForeignPort, nOwnPort, IPPROTO_TCP),
	m_bActiveOpen (TRUE),
	m_State (TCPStateClosed),
	m_nErrno (0),
	m_RetransmissionQueue (TCP_CONFIG_RETRANS_BUFFER_SIZE),
	m_bRetransmit (FALSE),
	m_bSendSYN (FALSE),
	m_bFINQueued (FALSE),
	m_nRetransmissionCount (0),
	m_bTimedOut (FALSE),
	m_pTimer (CTimer::Get ()),
	m_nSND_WND (TCP_CONFIG_WINDOW),
	m_nSND_UP (0),
	m_nRCV_NXT (0),
	m_nRCV_WND (TCP_CONFIG_WINDOW),
	m_nIRS (0),
	m_nSND_MSS (536)	// RFC 1122 section 4.2.2.6
{
	m_pTxBuffer = new u8[FRAME_BUFFER_SIZE];
	assert (m_pTxBuffer != 0);
	
	m_pTempBuffer = new u8[FRAME_BUFFER_SIZE];
	assert (m_pTempBuffer != 0);
	
	for (unsigned nTimer = TCPTimerUser; nTimer < TCPTimerUnknown; nTimer++)
	{
		m_hTimer[nTimer] = 0;
	}

	m_nISS = CalculateISN ();
	m_RTOCalculator.Initialize (m_nISS);

	m_nSND_UNA = m_nISS;
	m_nSND_NXT = m_nISS+1;

	if (SendSegment (TCP_FLAG_SYN, m_nISS))
	{
		m_RTOCalculator.SegmentSent (m_nISS);
		NEW_STATE (TCPStateSynSent);
		m_nRetransmissionCount = MAX_RETRANSMISSIONS;
		StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ());
	}
}
Exemplo n.º 4
0
void State_Inventory::Update()
{
	unsigned key = t.Key();
	switch( key ){
		case 'a':
			s.pop();
			break;
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			if( key-48 > m->items->size() ) return;
			s.push(NEW_STATE(ViewItem, (*m->items)[key-49]));
			break;
	}
}
Exemplo n.º 5
0
int re_match(regexp_t bufp, unsigned char *string, int size, int pos,
             regexp_registers_t old_regs)
{
	unsigned char *code;
	unsigned char *translate;
	unsigned char *text;
	unsigned char *textstart;
	unsigned char *textend;
	int a;
	int b;
	int ch;
	int reg;
	int match_end;
	unsigned char *regstart;
	unsigned char *regend;
	int regsize;
	match_state state;
  
	assert(pos >= 0 && size >= 0);
	assert(pos <= size);
  
	text = string + pos;
	textstart = string;
	textend = string + size;
  
	code = bufp->buffer;
  
	translate = bufp->translate;
  
	NEW_STATE(state, bufp->num_registers);

  continue_matching:
	switch (*code++)
	{
	case Cend:
	{
		match_end = text - textstart;
		if (old_regs)
		{
			old_regs->start[0] = pos;
			old_regs->end[0] = match_end;
			if (!bufp->uses_registers)
			{
				for (a = 1; a < RE_NREGS; a++)
				{
					old_regs->start[a] = -1;
					old_regs->end[a] = -1;
				}
			}
			else
			{
				for (a = 1; a < bufp->num_registers; a++)
				{
					if ((GET_REG_START(state, a) == NULL) ||
					    (GET_REG_END(state, a) == NULL))
					{
						old_regs->start[a] = -1;
						old_regs->end[a] = -1;
						continue;
					}
					old_regs->start[a] = GET_REG_START(state, a) - textstart;
					old_regs->end[a] = GET_REG_END(state, a) - textstart;
				}
				for (; a < RE_NREGS; a++)
				{
					old_regs->start[a] = -1;
					old_regs->end[a] = -1;
				}
			}
		}
		FREE_STATE(state);
		return match_end - pos;
	}
	case Cbol:
	{
		if (text == textstart || text[-1] == '\n')
			goto continue_matching;
		goto fail;
	}
	case Ceol:
	{
		if (text == textend || *text == '\n')
			goto continue_matching;
		goto fail;
	}
	case Cset:
	{
		NEXTCHAR(ch);
		if (code[ch/8] & (1<<(ch & 7)))
		{
			code += 256/8;
			goto continue_matching;
		}
		goto fail;
	}
	case Cexact:
	{
		NEXTCHAR(ch);
		if (ch != (unsigned char)*code++)
			goto fail;
		goto continue_matching;
	}
	case Canychar:
	{
		NEXTCHAR(ch);
		if (ch == '\n')
			goto fail;
		goto continue_matching;
	}
	case Cstart_memory:
	{
		reg = *code++;
		SET_REG_START(state, reg, text, goto error);
		goto continue_matching;
	}
	case Cend_memory:
	{
		reg = *code++;
		SET_REG_END(state, reg, text, goto error);
		goto continue_matching;
	}
	case Cmatch_memory:
	{
		reg = *code++;
		regstart = GET_REG_START(state, reg);
		regend = GET_REG_END(state, reg);
		if ((regstart == NULL) || (regend == NULL))
			goto fail;  /* or should we just match nothing? */
		regsize = regend - regstart;

		if (regsize > (textend - text))
			goto fail;
		if(translate)
		{
			for (; regstart < regend; regstart++, text++)
				if (translate[*regstart] != translate[*text])
					goto fail;
		}
		else
			for (; regstart < regend; regstart++, text++)
				if (*regstart != *text)
					goto fail;
		goto continue_matching;
	}
	case Cupdate_failure_jump:
	{
		UPDATE_FAILURE(state, text, goto error);
		/* fall to next case */
	}
	/* treat Cstar_jump just like Cjump if it hasn't been optimized */
	case Cstar_jump:
	case Cjump:
	{
		a = (unsigned char)*code++;
		a |= (unsigned char)*code++ << 8;
		code += (int)SHORT(a);
		if (code<bufp->buffer || bufp->buffer+bufp->used<code) {
		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cjump)");
			FREE_STATE(state);
            	        return -2;
         	}
		goto continue_matching;
	}
	case Cdummy_failure_jump:
	{
                unsigned char *failuredest;
	  
		a = (unsigned char)*code++;
		a |= (unsigned char)*code++ << 8;
		a = (int)SHORT(a);
		assert(*code == Cfailure_jump);
		b = (unsigned char)code[1];
		b |= (unsigned char)code[2] << 8;
                failuredest = code + (int)SHORT(b) + 3;
		if (failuredest<bufp->buffer || bufp->buffer+bufp->used < failuredest) {
		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cdummy_failure_jump failuredest)");
			FREE_STATE(state);
            	        return -2;
		}
		PUSH_FAILURE(state, failuredest, NULL, goto error);
		code += a;
		if (code<bufp->buffer || bufp->buffer+bufp->used < code) {
		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cdummy_failure_jump code)");
			FREE_STATE(state);
            	        return -2;
         	}
		goto continue_matching;
	}
	case Cfailure_jump:
	{
		a = (unsigned char)*code++;
		a |= (unsigned char)*code++ << 8;
		a = (int)SHORT(a);
		if (code+a<bufp->buffer || bufp->buffer+bufp->used < code+a) {
		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cfailure_jump)");
			FREE_STATE(state);
            	        return -2;
         	}
		PUSH_FAILURE(state, code + a, text, goto error);
		goto continue_matching;
	}
	case Crepeat1:
	{
		unsigned char *pinst;
		a = (unsigned char)*code++;
		a |= (unsigned char)*code++ << 8;
		a = (int)SHORT(a);
		pinst = code + a;
		if (pinst<bufp->buffer || bufp->buffer+bufp->used<pinst) {
		        PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Crepeat1)");
			FREE_STATE(state);
            	        return -2;
         	}
		/* pinst is sole instruction in loop, and it matches a
		 * single character.  Since Crepeat1 was originally a
		 * Cupdate_failure_jump, we also know that backtracking
		 * is useless: so long as the single-character
		 * expression matches, it must be used.  Also, in the
		 * case of +, we've already matched one character, so +
		 * can't fail: nothing here can cause a failure.  */
		switch (*pinst++)
		{
		case Cset:
		  {
		        if (translate)
			{
				while (text < textend)
				{
					ch = translate[(unsigned char)*text];
					if (pinst[ch/8] & (1<<(ch & 7)))
						text++;
					else
						break;
				}
			}
			else
			{
				while (text < textend)
				{
					ch = (unsigned char)*text;
					if (pinst[ch/8] & (1<<(ch & 7)))
						text++;
					else
						break;
				}
			}
			break;
                }
		case Cexact:
		{
			ch = (unsigned char)*pinst;
			if (translate)
			{
				while (text < textend &&
				       translate[(unsigned char)*text] == ch)
					text++;
			}
			else
			{
				while (text < textend && (unsigned char)*text == ch)
					text++;
			}
			break;
		}
		case Canychar:
		{
			while (text < textend && (unsigned char)*text != '\n')
				text++;
			break;
		}
		case Csyntaxspec:
		{
			a = (unsigned char)*pinst;
			if (translate)
			{
				while (text < textend &&
				       (SYNTAX(translate[*text]) & a) )
					text++;
			}
			else
			{
				while (text < textend && (SYNTAX(*text) & a) )
					text++;
			}
			break;
		}
		case Cnotsyntaxspec:
		{
			a = (unsigned char)*pinst;
			if (translate)
			{
				while (text < textend &&
				       !(SYNTAX(translate[*text]) & a) )
					text++;
			}
			else
			{
				while (text < textend && !(SYNTAX(*text) & a) )
					text++;
			}
			break;
		}
		default:
		{
		        FREE_STATE(state);
		        PyErr_SetString(PyExc_SystemError, "Unknown regex opcode: memory corrupted?");
		        return -2;
			/*NOTREACHED*/
		}
		}
		/* due to the funky way + and * are compiled, the top
		 * failure- stack entry at this point is actually a
		 * success entry -- update it & pop it */
		UPDATE_FAILURE(state, text, goto error);
		goto fail;      /* i.e., succeed <wink/sigh> */
	}
	case Cbegbuf:
	{
		if (text == textstart)
			goto continue_matching;
		goto fail;
	}
	case Cendbuf:
	{
		if (text == textend)
			goto continue_matching;
		goto fail;
	}
	case Cwordbeg:
	{
		if (text == textend)
			goto fail;
		if (!(SYNTAX(*text) & Sword)) 
			goto fail;
		if (text == textstart)
			goto continue_matching;
		if (!(SYNTAX(text[-1]) & Sword))
			goto continue_matching;
		goto fail;
	}
	case Cwordend:
	{
		if (text == textstart)
			goto fail;
		if (!(SYNTAX(text[-1]) & Sword))
			goto fail;
		if (text == textend)
			goto continue_matching;
		if (!(SYNTAX(*text) & Sword))
		        goto continue_matching;
                goto fail;
	}
	case Cwordbound:
	{
		/* Note: as in gnu regexp, this also matches at the
		 * beginning and end of buffer.  */

		if (text == textstart || text == textend)
			goto continue_matching;
		if ((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword))
			goto continue_matching;
		goto fail;
	}
	case Cnotwordbound:
	{
		/* Note: as in gnu regexp, this never matches at the
		 * beginning and end of buffer.  */
		if (text == textstart || text == textend)
			goto fail;
		if (!((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword)))
      		        goto continue_matching;
		goto fail;
	}
	case Csyntaxspec:
	{
		NEXTCHAR(ch);
		if (!(SYNTAX(ch) & (unsigned char)*code++))
			goto fail;
		goto continue_matching;
	}
	case Cnotsyntaxspec:
	{
		NEXTCHAR(ch);
		if (SYNTAX(ch) & (unsigned char)*code++)
			goto fail;
		goto continue_matching;
	}
	default:
	{
	        FREE_STATE(state);
	        PyErr_SetString(PyExc_SystemError, "Unknown regex opcode: memory corrupted?");
		return -2;
		/*NOTREACHED*/
	}
	}
	
	

#if 0 /* This line is never reached --Guido */
	abort();
#endif
	/*
	 *NOTREACHED
	 */

	/* Using "break;" in the above switch statement is equivalent to "goto fail;" */
  fail:
	POP_FAILURE(state, code, text, goto done_matching, goto error);
	goto continue_matching;
  
  done_matching:
/*   if(translated != NULL) */
/*      free(translated); */
	FREE_STATE(state);
	return -1;

  error:
/*   if (translated != NULL) */
/*      free(translated); */
	FREE_STATE(state);
	return -2;
}
Exemplo n.º 6
0
int CTCPConnection::PacketReceived (const void	*pPacket,
				    unsigned	 nLength,
				    CIPAddress	&rSenderIP,
				    int		 nProtocol)
{
	if (nProtocol != IPPROTO_TCP)
	{
		return 0;
	}

	if (nLength < sizeof (TTCPHeader))
	{
		return -1;
	}

	assert (pPacket != 0);
	TTCPHeader *pHeader = (TTCPHeader *) pPacket;

	if (m_nOwnPort != be2le16 (pHeader->nDestPort))
	{
		return 0;
	}
	
	if (m_State != TCPStateListen)
	{
		if (   m_ForeignIP != rSenderIP
		    || m_nForeignPort != be2le16 (pHeader->nSourcePort))
		{
			return 0;
		}
	}
	else
	{
		if (!(pHeader->nDataOffsetFlags & TCP_FLAG_SYN))
		{
			return 0;
		}

		m_Checksum.SetDestinationAddress (rSenderIP);
	}

	if (m_Checksum.Calculate (pPacket, nLength) != CHECKSUM_OK)
	{
		return 0;
	}

	u16 nFlags = pHeader->nDataOffsetFlags;
	u32 nDataOffset = TCP_DATA_OFFSET (pHeader->nDataOffsetFlags)*4;
	u32 nDataLength = nLength-nDataOffset;

	// Current Segment Variables
	u32 nSEG_SEQ = be2le32 (pHeader->nSequenceNumber);
	u32 nSEG_ACK = be2le32 (pHeader->nAcknowledgmentNumber);

	u32 nSEG_LEN = nDataLength;
	if (nFlags & TCP_FLAG_SYN)
	{
		nSEG_LEN++;
	}
	if (nFlags & TCP_FLAG_FIN)
	{
		nSEG_LEN++;
	}
	
	u32 nSEG_WND = be2le16 (pHeader->nWindow);
	//u16 nSEG_UP  = be2le16 (pHeader->nUrgentPointer);
	//u32 nSEG_PRC;	// segment precedence value

	ScanOptions (pHeader);

#ifdef TCP_DEBUG
	CLogger::Get ()->Write (FromTCP, LogDebug,
				"rx %c%c%c%c%c%c, seq %u, ack %u, win %u, len %u",
				nFlags & TCP_FLAG_URGENT ? 'U' : '-',
				nFlags & TCP_FLAG_ACK    ? 'A' : '-',
				nFlags & TCP_FLAG_PUSH   ? 'P' : '-',
				nFlags & TCP_FLAG_RESET  ? 'R' : '-',
				nFlags & TCP_FLAG_SYN    ? 'S' : '-',
				nFlags & TCP_FLAG_FIN    ? 'F' : '-',
				nSEG_SEQ-m_nIRS,
				nFlags & TCP_FLAG_ACK ? nSEG_ACK-m_nISS : 0,
				nSEG_WND,
				nDataLength);

	DumpStatus ();
#endif

	boolean bAcceptable = FALSE;

	// RFC 793 section 3.9 "SEGMENT ARRIVES"
	switch (m_State)
	{
	case TCPStateClosed:
		if (nFlags & TCP_FLAG_RESET)
		{
			// ignore
		}
		else if (!(nFlags & TCP_FLAG_ACK))
		{
			m_ForeignIP.Set (rSenderIP);
			m_nForeignPort = be2le16 (pHeader->nSourcePort);
			m_Checksum.SetDestinationAddress (rSenderIP);

			SendSegment (TCP_FLAG_RESET | TCP_FLAG_ACK, 0, nSEG_SEQ+nSEG_LEN);
		}
		else
		{
			m_ForeignIP.Set (rSenderIP);
			m_nForeignPort = be2le16 (pHeader->nSourcePort);
			m_Checksum.SetDestinationAddress (rSenderIP);

			SendSegment (TCP_FLAG_RESET, nSEG_ACK);
		}
		break;

	case TCPStateListen:
		if (nFlags & TCP_FLAG_RESET)
		{
			// ignore
		}
		else if (nFlags & TCP_FLAG_ACK)
		{
			m_ForeignIP.Set (rSenderIP);
			m_nForeignPort = be2le16 (pHeader->nSourcePort);
			m_Checksum.SetDestinationAddress (rSenderIP);

			SendSegment (TCP_FLAG_RESET, nSEG_ACK);
		}
		else if (nFlags & TCP_FLAG_SYN)
		{
			m_nRCV_NXT = nSEG_SEQ+1;
			m_nIRS = nSEG_SEQ;

			m_nSND_WND = nSEG_WND;
			m_nSND_WL1 = nSEG_SEQ;
			m_nSND_WL2 = nSEG_ACK;
	
			assert (nSEG_LEN > 0);

			if (nDataLength > 0)
			{
				m_RxQueue.Enqueue ((u8 *) pPacket+nDataOffset, nDataLength);
			}

			m_nISS = CalculateISN ();
			m_RTOCalculator.Initialize (m_nISS);

			m_ForeignIP.Set (rSenderIP);
			m_nForeignPort = be2le16 (pHeader->nSourcePort);
			m_Checksum.SetDestinationAddress (rSenderIP);

			SendSegment (TCP_FLAG_SYN | TCP_FLAG_ACK, m_nISS, m_nRCV_NXT);
			m_RTOCalculator.SegmentSent (m_nISS);

			m_nSND_NXT = m_nISS+1;
			m_nSND_UNA = m_nISS;
			
			NEW_STATE (TCPStateSynReceived);

			m_Event.Set ();
		}
		break;

	case TCPStateSynSent:
		if (nFlags & TCP_FLAG_ACK)
		{
			if (!bwh (m_nISS, nSEG_ACK, m_nSND_NXT))
			{
				if (!(nFlags & TCP_FLAG_RESET))
				{
					SendSegment (TCP_FLAG_RESET, nSEG_ACK);
				}

				return 1;
			}
			else if (bwlh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT))
			{
				bAcceptable = TRUE;
			}
		}

		if (nFlags & TCP_FLAG_RESET)
		{
			if (bAcceptable)
			{
				NEW_STATE (TCPStateClosed);
				m_bSendSYN = FALSE;
				m_nErrno = -1;

				m_Event.Set ();
			}
			
			break;
		}
		
		if (   (nFlags & TCP_FLAG_ACK)
		    && !bAcceptable)
		{
			break;
		}

		if (nFlags & TCP_FLAG_SYN)
		{
			m_nRCV_NXT = nSEG_SEQ+1;
			m_nIRS = nSEG_SEQ;

			if (nFlags & TCP_FLAG_ACK)
			{
				m_RTOCalculator.SegmentAcknowledged (nSEG_ACK);

				if (nSEG_ACK-m_nSND_UNA > 1)
				{
					m_RetransmissionQueue.Advance (nSEG_ACK-m_nSND_UNA-1);
				}

				m_nSND_UNA = nSEG_ACK;
			}

			if (gt (m_nSND_UNA, m_nISS))
			{
				NEW_STATE (TCPStateEstablished);
				m_bSendSYN = FALSE;

				StopTimer (TCPTimerRetransmission);

				// next transmission starts with this count
				m_nRetransmissionCount = MAX_RETRANSMISSIONS;

				m_Event.Set ();

				// RFC 1122 section 4.2.2.20 (c)
				m_nSND_WND = nSEG_WND;
				m_nSND_WL1 = nSEG_SEQ;
				m_nSND_WL2 = nSEG_ACK;
	
				SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);
				
				if (   (nFlags & TCP_FLAG_FIN)		// other controls?
				    || nDataLength > 0)
				{
					goto StepSix;
				}

				break;
			}
			else
			{
				NEW_STATE (TCPStateSynReceived);
				m_bSendSYN = FALSE;
				SendSegment (TCP_FLAG_SYN | TCP_FLAG_ACK, m_nISS, m_nRCV_NXT);
				m_RTOCalculator.SegmentSent (m_nISS);
				m_nRetransmissionCount = MAX_RETRANSMISSIONS;
				StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ());

				if (   (nFlags & TCP_FLAG_FIN)		// other controls?
				    || nDataLength > 0)
				{
					if (nFlags & TCP_FLAG_FIN)
					{
						SendSegment (TCP_FLAG_RESET, m_nSND_NXT);
						NEW_STATE (TCPStateClosed);
					}

					if (nDataLength > 0)
					{
						m_RxQueue.Enqueue ((u8 *) pPacket+nDataOffset, nDataLength);
					}

					break;
				}
			}
		}
		break;

	case TCPStateSynReceived:
	case TCPStateEstablished:
	case TCPStateFinWait1:
	case TCPStateFinWait2:
	case TCPStateCloseWait:
	case TCPStateClosing:
	case TCPStateLastAck:
	case TCPStateTimeWait:
		// step 1 ( check sequence number)
		if (m_nRCV_WND > 0)
		{
			if (nSEG_LEN == 0)
			{
				if (bwl (m_nRCV_NXT, nSEG_SEQ, m_nRCV_NXT+m_nRCV_WND))
				{
					bAcceptable = TRUE;
				}
			}
			else
			{
				if (   bwl (m_nRCV_NXT, nSEG_SEQ, m_nRCV_NXT+m_nRCV_WND)
				    || bwl (m_nRCV_NXT, nSEG_SEQ+nSEG_LEN-1, m_nRCV_NXT+m_nRCV_WND))
				{
					bAcceptable = TRUE;
				}
			}
		}
		else
		{
			if (nSEG_LEN == 0)
			{
				if (nSEG_SEQ == m_nRCV_NXT)
				{
					bAcceptable = TRUE;
				}
			}
		}

		if (   !bAcceptable
		    && m_State != TCPStateSynReceived)
		{
			SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);
			break;
		}

		// step 2 (check RST bit)
		if (nFlags & TCP_FLAG_RESET)
		{
			switch (m_State)
			{
			case TCPStateSynReceived:
				m_RetransmissionQueue.Flush ();
				if (!m_bActiveOpen)
				{
					NEW_STATE (TCPStateListen);
					return 1;
				}
				else
				{
					m_nErrno = -1;
					NEW_STATE (TCPStateClosed);
					m_Event.Set ();
					return 1;
					
				}
				break;

			case TCPStateEstablished:
			case TCPStateFinWait1:
			case TCPStateFinWait2:
			case TCPStateCloseWait:
				m_nErrno = -1;
				m_RetransmissionQueue.Flush ();
				m_TxQueue.Flush ();
				m_RxQueue.Flush ();
				NEW_STATE (TCPStateClosed);
				m_Event.Set ();
				return 1;

			case TCPStateClosing:
			case TCPStateLastAck:
			case TCPStateTimeWait:
				NEW_STATE (TCPStateClosed);
				m_Event.Set ();
				return 1;

			default:
				UNEXPECTED_STATE ();
				return 1;
			}
		}

		// step 3 (check security and precedence, not supported)
		
		// step 4 (check SYN bit)
		if (nFlags & TCP_FLAG_SYN)
		{
			// RFC 1122 section 4.2.2.20 (e)
			if (   m_State == TCPStateSynReceived
			    && !m_bActiveOpen)
			{
				NEW_STATE (TCPStateListen);
				return 1;
			}
			
			SendSegment (TCP_FLAG_RESET, m_nSND_NXT);
			m_nErrno = -1;
			m_RetransmissionQueue.Flush ();
			m_TxQueue.Flush ();
			m_RxQueue.Flush ();
			NEW_STATE (TCPStateClosed);
			m_Event.Set ();
			return 1;
		}

		// step 5 (check ACK field)
		if (!(nFlags & TCP_FLAG_ACK))
		{
			return 1;
		}

		switch (m_State)
		{
		case TCPStateSynReceived:
			if (bwlh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT))
			{
				// RFC 1122 section 4.2.2.20 (f)
				m_nSND_WND = nSEG_WND;
				m_nSND_WL1 = nSEG_SEQ;
				m_nSND_WL2 = nSEG_ACK;

				m_nSND_UNA = nSEG_ACK;		// got ACK for SYN

				m_RTOCalculator.SegmentAcknowledged (nSEG_ACK);

				NEW_STATE (TCPStateEstablished);

				// next transmission starts with this count
				m_nRetransmissionCount = MAX_RETRANSMISSIONS;
			}
			else
			{
				SendSegment (TCP_FLAG_RESET, nSEG_ACK);
			}
			break;

		case TCPStateEstablished:
		case TCPStateFinWait1:
		case TCPStateFinWait2:
		case TCPStateCloseWait:
		case TCPStateClosing:
			if (bwh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT))
			{
				m_RTOCalculator.SegmentAcknowledged (nSEG_ACK);

				unsigned nBytesAck = nSEG_ACK-m_nSND_UNA;
				m_nSND_UNA = nSEG_ACK;

				if (nSEG_ACK == m_nSND_NXT)	// all segments are acknowledged
				{
					StopTimer (TCPTimerRetransmission);

					// next transmission starts with this count
					m_nRetransmissionCount = MAX_RETRANSMISSIONS;

					m_Event.Set ();
				}

				if (   m_State == TCPStateFinWait1
				    || m_State == TCPStateClosing)
				{
					nBytesAck--;		// acknowledged FIN does not count
					m_bFINQueued = FALSE;
				}

				if (   m_State == TCPStateEstablished
				    && nBytesAck == 1)
				{
					nBytesAck--;
				}
				
				if (nBytesAck > 0)
				{
					m_RetransmissionQueue.Advance (nBytesAck);
				}

				// update send window
				if (   lt (m_nSND_WL1, nSEG_SEQ)
				    || (   m_nSND_WL1 == nSEG_SEQ
				        && le (m_nSND_WL2, nSEG_ACK)))
				{
					m_nSND_WND = nSEG_WND;
					m_nSND_WL1 = nSEG_SEQ;
					m_nSND_WL2 = nSEG_ACK;
				}
			}
			else if (le (nSEG_ACK, m_nSND_UNA))	// RFC 1122 section 4.2.2.20 (g)
			{
				// ignore duplicate ACK ...
				
				// RFC 1122 section 4.2.2.20 (g)
				if (bwlh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT))
				{
					// ... but update send window
					if (   lt (m_nSND_WL1, nSEG_SEQ)
					    || (   m_nSND_WL1 == nSEG_SEQ
						&& le (m_nSND_WL2, nSEG_ACK)))
					{
						m_nSND_WND = nSEG_WND;
						m_nSND_WL1 = nSEG_SEQ;
						m_nSND_WL2 = nSEG_ACK;
					}
				}
			}
			else if (gt (nSEG_ACK, m_nSND_NXT))
			{
				SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);
				return 1;
			}
			
			switch (m_State)
			{
			case TCPStateEstablished:
			case TCPStateCloseWait:
				break;

			case TCPStateFinWait1:
				if (nSEG_ACK == m_nSND_NXT)	// if our FIN is now acknowledged
				{
					m_RTOCalculator.SegmentAcknowledged (nSEG_ACK);

					m_bFINQueued = FALSE;
					StopTimer (TCPTimerRetransmission);
					NEW_STATE (TCPStateFinWait2);
				}
				else
				{
					break;
				}
				// fall through

			case TCPStateFinWait2:
				if (m_RetransmissionQueue.IsEmpty ())
				{
					m_Event.Set ();
				}
				break;
				
			case TCPStateClosing:
				if (nSEG_ACK == m_nSND_NXT)	// if our FIN is now acknowledged
				{
					m_RTOCalculator.SegmentAcknowledged (nSEG_ACK);

					m_bFINQueued = FALSE;
					StopTimer (TCPTimerRetransmission);
					NEW_STATE (TCPStateTimeWait);
					StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT);
				}
				break;

			default:
				UNEXPECTED_STATE ();
				break;
			}
			break;
			
		case TCPStateLastAck:
			if (nSEG_ACK == m_nSND_NXT)	// if our FIN is now acknowledged
			{
				m_bFINQueued = FALSE;
				NEW_STATE (TCPStateClosed);
				m_Event.Set ();
				return 1;
			}
			break;

		case TCPStateTimeWait:
			if (nSEG_ACK == m_nSND_NXT)	// if our FIN is now acknowledged
			{
				m_bFINQueued = FALSE;
				SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);
				StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT);
			}
			break;

		default:
			UNEXPECTED_STATE ();
			break;
		}

		// step 6 (check URG bit, not supported)
	StepSix:

		// step 7 (process text segment)
		if (nSEG_LEN == 0)
		{
			return 1;
		}
		
		switch (m_State)
		{
		case TCPStateEstablished:
		case TCPStateFinWait1:
		case TCPStateFinWait2:
			if (nSEG_SEQ == m_nRCV_NXT)
			{
				if (nDataLength > 0)
				{
					m_RxQueue.Enqueue ((u8 *) pPacket+nDataOffset, nDataLength);

					m_nRCV_NXT += nDataLength;

					// m_nRCV_WND should be adjusted here (section 3.7)

					// following ACK could be piggybacked with data
					SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);

					if (nFlags & TCP_FLAG_PUSH)
					{
						m_Event.Set ();
					}
				}
			}
			else
			{
				SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);
			}
			break;

		case TCPStateCloseWait:
		case TCPStateClosing:
		case TCPStateLastAck:
		case TCPStateTimeWait:
			break;

		default:
			UNEXPECTED_STATE ();
			break;
		}

		// step 8 (check FIN bit)
		if (   m_State == TCPStateClosed
		    || m_State == TCPStateListen
		    || m_State == TCPStateSynSent)
		{
			return 1;
		}
			
		if (!(nFlags & TCP_FLAG_FIN))
		{
			return 1;
		}

		// connection is closing
		m_nRCV_NXT++;
		SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);
		
		switch (m_State)
		{
		case TCPStateSynReceived:
		case TCPStateEstablished:
			NEW_STATE (TCPStateCloseWait);
			m_Event.Set ();
			break;

		case TCPStateFinWait1:
			if (nSEG_ACK == m_nSND_NXT)	// if our FIN is now acknowledged
			{
				m_bFINQueued = FALSE;
				StopTimer (TCPTimerRetransmission);
				StopTimer (TCPTimerUser);
				NEW_STATE (TCPStateTimeWait);
				StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT);
			}
			else
			{
				NEW_STATE (TCPStateClosing);
			}
			break;

		case TCPStateFinWait2:
			StopTimer (TCPTimerRetransmission);
			StopTimer (TCPTimerUser);
			NEW_STATE (TCPStateTimeWait);
			StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT);
			break;

		case TCPStateCloseWait:
		case TCPStateClosing:
		case TCPStateLastAck:
			break;
			
		case TCPStateTimeWait:
			StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT);
			break;

		default:
			UNEXPECTED_STATE ();
			break;
		}
		break;
	}

	return 1;
}
Exemplo n.º 7
0
void CTCPConnection::Process (void)
{
	if (m_bTimedOut)
	{
		m_nErrno = -1;
		NEW_STATE (TCPStateClosed);
		m_Event.Set ();
		return;
	}

	switch (m_State)
	{
	case TCPStateClosed:
	case TCPStateListen:
	case TCPStateFinWait2:
	case TCPStateTimeWait:
		return;

	case TCPStateSynSent:
	case TCPStateSynReceived:
		if (m_bSendSYN)
		{
			m_bSendSYN = FALSE;
			if (m_State == TCPStateSynSent)
			{
				SendSegment (TCP_FLAG_SYN, m_nISS);
			}
			else
			{
				SendSegment (TCP_FLAG_SYN | TCP_FLAG_ACK, m_nISS, m_nRCV_NXT);
			}
			m_RTOCalculator.SegmentSent (m_nISS);
			StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ());
		}
		return;
		
	case TCPStateEstablished:
	case TCPStateFinWait1:
	case TCPStateCloseWait:
	case TCPStateClosing:
	case TCPStateLastAck:
		if (   m_RetransmissionQueue.IsEmpty ()
		    && m_TxQueue.IsEmpty ()
		    && m_bFINQueued)
		{
			SendSegment (TCP_FLAG_FIN | TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT);
			m_RTOCalculator.SegmentSent (m_nSND_NXT);
			m_nSND_NXT++;
			NEW_STATE (m_StateAfterFIN);
			m_bFINQueued = FALSE;
			StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ());
		}
		break;
	}

	assert (m_pTempBuffer != 0);
	unsigned nLength;
	while (    m_RetransmissionQueue.GetFreeSpace () >= FRAME_BUFFER_SIZE
		&& (nLength = m_TxQueue.Dequeue (m_pTempBuffer)) > 0)
	{
#ifdef TCP_DEBUG
		CLogger::Get ()->Write (FromTCP, LogDebug, "Transfering %u bytes into RT buffer", nLength);
#endif

		m_RetransmissionQueue.Write (m_pTempBuffer, nLength);
	}

	if (m_bRetransmit)
	{
#ifdef TCP_DEBUG
		CLogger::Get ()->Write (FromTCP, LogDebug, "Retransmission (nxt %u, una %u)", m_nSND_NXT-m_nISS, m_nSND_UNA-m_nISS);
#endif
		m_bRetransmit = FALSE;
		m_RetransmissionQueue.Reset ();
		m_nSND_NXT = m_nSND_UNA;
	}

	u32 nBytesAvail;
	u32 nWindowLeft;
	while (   (nBytesAvail = m_RetransmissionQueue.GetBytesAvailable ()) > 0
	       && (nWindowLeft = m_nSND_UNA+m_nSND_WND-m_nSND_NXT) > 0)
	{
		nLength = min (nBytesAvail, nWindowLeft);
		nLength = min (nLength, m_nSND_MSS);

#ifdef TCP_DEBUG
		CLogger::Get ()->Write (FromTCP, LogDebug, "Transfering %u bytes into TX buffer", nLength);
#endif

		assert (nLength <= FRAME_BUFFER_SIZE);
		m_RetransmissionQueue.Read (m_pTempBuffer, nLength);

		unsigned nFlags = TCP_FLAG_ACK;
		if (   m_RetransmissionQueue.IsEmpty ()
		    && m_TxQueue.IsEmpty ())
		{
			nFlags |= TCP_FLAG_PUSH;
		}

		SendSegment (nFlags, m_nSND_NXT, m_nRCV_NXT, m_pTempBuffer, nLength);
		m_RTOCalculator.SegmentSent (m_nSND_NXT, nLength);
		m_nSND_NXT += nLength;
		StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ());
	}
}
Exemplo n.º 8
0
static
void register_console_config_check_commands() {
  cmd_info_t *showcmd, *nocmd, *confcmd, *conftcmd, *conftnocmd, *lscmd;
  noit_console_state_t *tl, *_conf_t_check_state, *_unset_state,
                       *_attr_state, *_uattr_state;

  tl = noit_console_state_initial();
  showcmd = noit_console_state_get_cmd(tl, "show");
  nocmd = noit_console_state_get_cmd(tl, "no");
  confcmd = noit_console_state_get_cmd(tl, "configure");
  conftcmd = noit_console_state_get_cmd(confcmd->dstate, "terminal");
  conftnocmd = noit_console_state_get_cmd(conftcmd->dstate, "no");
  lscmd = noit_console_state_get_cmd(conftcmd->dstate, "ls");
  lscmd->func = noit_console_config_show;
  /* attribute <attrname> <value> */
  NEW_STATE(_attr_state);
  noit_console_state_add_check_attrs(_attr_state, noit_conf_check_set_attr,
                                     "/checks");
 
  /* no attribute <attrname> <value> */
  NEW_STATE(_uattr_state);
  noit_console_state_add_check_attrs(_uattr_state, noit_conf_check_unset_attr,
                                     "/checks");
  NEW_STATE(_unset_state);
  DELEGATE_CMD(_unset_state, "attribute",
               noit_console_opt_delegate, _uattr_state);
  ADD_CMD(_unset_state, "config",
          noit_console_config_unsetconfig, NULL, NULL, NULL);

  DELEGATE_CMD(conftnocmd->dstate, "attribute",
               noit_console_opt_delegate, _uattr_state);
  ADD_CMD(conftnocmd->dstate, "config",
          noit_console_config_unsetconfig, NULL, NULL, NULL);
  ADD_CMD(conftnocmd->dstate, "check",
          noit_console_config_nocheck, NULL, NULL, NULL);
 
  NEW_STATE(_conf_t_check_state);
  _conf_t_check_state->console_prompt_function = conf_t_check_prompt;
  DELEGATE_CMD(_conf_t_check_state, "attribute",
               noit_console_opt_delegate, _attr_state);
  DELEGATE_CMD(_conf_t_check_state, "no",
               noit_console_opt_delegate, _unset_state);
  ADD_CMD(_conf_t_check_state, "config",
          noit_console_config_setconfig, NULL, NULL, NULL);
  ADD_CMD(_conf_t_check_state, "status",
          noit_console_show_check, NULL, NULL, NULL);
  ADD_CMD(_conf_t_check_state, "exit",
          noit_console_config_cd, NULL, NULL, "..");
  ADD_CMD(_conf_t_check_state, "check",
          noit_console_check, noit_console_conf_check_opts,
          _conf_t_check_state, "..");

  ADD_CMD(conftcmd->dstate, "config",
          noit_console_config_setconfig, NULL, NULL, NULL);
  ADD_CMD(conftcmd->dstate, "check",
          noit_console_check, noit_console_conf_check_opts,
          _conf_t_check_state, NULL);

  ADD_CMD(showcmd->dstate, "check",
          noit_console_show_check, noit_console_check_opts, NULL, NULL);

  ADD_CMD(tl, "watch",
          noit_console_watch_check, noit_console_check_opts, NULL, (void *)1);

  ADD_CMD(nocmd->dstate, "watch",
          noit_console_watch_check, noit_console_check_opts, NULL, (void *)0);

  DELEGATE_CMD(conftcmd->dstate, "attribute",
               noit_console_opt_delegate, _attr_state);

  ADD_CMD(tl, "reload", noit_conf_checks_reload, NULL, NULL, NULL);
}