Exemple #1
0
/** \brief Process recieved ICMP datagram
 *	\ingroup periodic_functions
 * 	\author 
 *		\li Jari Lahti ([email protected])
 *	\date 08.07.2002
 *	\param frame - pointer to received IP frame structure
 *	\param len - length of the received IP datagram (in bytes)
 *	\return 
 *		\li -1 - packet not OK (not proper ICMP or not ICMP at all)
 *		\li >=0 - packet OK
 *
 *	Invoke process_icmp_in whenever IP datagram containing ICMP message
 *	is detected (see main_demo.c for example main loop implementing this).
 *	
 *	This function simply checks correctnes of received ICMP message and
 *	send ICMP replies when requested.
 *
 */
INT16 process_icmp_in (struct ip_frame* frame, UINT16 len) 
{
	UINT8 type;
	UINT8 code;
	UINT16 checksum;
	UINT16 i;
	UINT16 j;
	UINT8 tbuf[16];
		
	/* Is this ICMP?	*/
	
	ICMP_DEBUGOUT("Processing ICMP...\n\r");
	
	if( frame->protocol != IP_ICMP ) 
	{
		ICMP_DEBUGOUT("ERROR: The protocol is not ICMP\n\r");
		return(-1);
	}
	
	/* Calculate checksum for received packet	*/

	checksum = 0;
	i        = len;
	
	NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
	
	while(i>15)
	{
		
		RECEIVE_NETWORK_BUF(tbuf, 16);	
		
		checksum = (UINT16)ip_checksum_buf (checksum, tbuf, 16);
		
		i -= 16;	
	}

	for(j=0; j < i; j++)
		checksum = ip_checksum(checksum, RECEIVE_NETWORK_B(), (UINT8)j);
	
	checksum = ~ checksum;
	
	if(checksum != IP_GOOD_CS) {
		ICMP_DEBUGOUT("ERROR: ICMP Checksum failed!\n\r");
		return (-1);
	}
	
	ICMP_DEBUGOUT("ICMP Checksum OK\n\r");
	
	/* Start processing the message	*/
	
	NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
	
	type = RECEIVE_NETWORK_B();
	code = RECEIVE_NETWORK_B();
	
	/* We have already checked the CS, skip it	*/
	
	(void)RECEIVE_NETWORK_B();
	(void)RECEIVE_NETWORK_B();

	switch(type) {
		case ICMP_ECHO_REQUEST:
		
			if(code != 0) {
				ICMP_DEBUGOUT("ERROR:Misformed ICMP ECHO Request\n\r");
				return(-1);
			}
			
			ICMP_DEBUGOUT("ICMP ECHO Request received\n\r");
			
			/* Is it a packet for setting temporary IP?	*/
			
			if(len == (ICMP_ECHOREQ_HLEN + ICMP_TEMPIPSET_DATALEN) )
			{
				/* Yep, set temporary IP address	*/
				
				ICMP_DEBUGOUT("PING with 102 bytes of data, getting temp. IP\r\n");			
				localmachine.localip = frame->dip;
				localmachine.defgw = frame->sip;
				localmachine.netmask = 0;
			}
			
			
			/* Same IP?		*/
			
			if(localmachine.localip != frame->dip)
				return(-1);

			/* Reply it	*/
			
			TXBUF[0] = ICMP_ECHO_REPLY;
			TXBUF[1] = 0;
			TXBUF[2] = 0;
			TXBUF[3] = 0;
			
			/* Copy with truncate if needed	*/
			
			if(len > NETWORK_TX_BUFFER_SIZE)
				len = NETWORK_TX_BUFFER_SIZE;
			
			RECEIVE_NETWORK_BUF(&TXBUF[4], len);
			
			/* Calculate Checksum for packet to be sent	*/
			
			checksum = 0;
			
			checksum = (UINT16)ip_checksum_buf(checksum, &TXBUF[0], len);
	
			checksum = ~ checksum;
			
			/* Put the checksum on place	*/
			
			TXBUF[2] = (UINT8)(checksum>>8);
			TXBUF[3] = (UINT8)checksum;
			
			/* Send it						*/
			
			(void)process_ip_out(frame->sip, IP_ICMP, 0, 100, &TXBUF[0], len);
			
			ICMP_DEBUGOUT("ICMP Reply sent\n\r");
			
			return(0);
			
		
		break;
		
		case ICMP_ECHO_REPLY:
		
		break;
	
		default:				/* Unrecognized ICMP message	*/
			
			ICMP_DEBUGOUT("Unregognized ICMP message\n\r");
			return(-1); 
	}
	
}
Exemple #2
0
/** \brief Send data to remote host using given UDP socket
 *  \ingroup udp_app_api
 * 	\author 
 *		\li Jari Lahti ([email protected])
 *	\date 26.07.2002
 *	\param sochandle handle to UDP socket to use
 *	\param remip remote IP address to which data should be sent
 *	\param remport remote port number to which data should be sent
 *	\param buf pointer to data buffer (start of user data)
 *	\param blen buffer length in bytes (without space reserved at the 
 *		beginning of buffer for headers)
 *	\param dlen length of user data to be sent (in bytes)
 *	\return 
 *		\li -1 - Error (general error, e.g. parameters)
 *		\li -2 - ARP or lower layer not ready, try again later
 *		\li -3 - Socket closed or invalid local port
 *		\li >0 - OK (number represents number of bytes actually sent)
 *
 *	\warning
 *		\li <i>buf</i> parameter is a pointer to data to be sent in 
 *		user buffer. But note that there <b>MUST</b> be sufficient
 *		free buffer space before that data for UDP header (of #UDP_HLEN
 *		size). 
 *
 *	Use this function to send data over an already opened UDP socket. 
 */
INT16 udp_send (INT8 sochandle, UINT32 remip, UINT16 remport, UINT8* buf, UINT16 blen, UINT16 dlen)
{
	struct ucb* soc;
	UINT8* user_buf_start;
	UINT16 cs;
	UINT8 cs_cnt;
	INT16 i;
	
	if( NO_OF_UDPSOCKETS < 0 )
		return(-1);
	
	if( NO_OF_UDPSOCKETS == 0 )
		return(-1);
	
	if( sochandle > NO_OF_UDPSOCKETS ) {
		UDP_DEBUGOUT("Socket handle non-valid\r\n");
		return(-1);
	}
	
	if( sochandle < 0 ) {
		UDP_DEBUGOUT("Socket handle non-valid\r\n");
		return(-1);
	}
	
	if(remip == 0) {
		UDP_DEBUGOUT("Remote IP 0 not allowed\r\n");
		return(-1);
	}
	
	if(remport == 0) {
		UDP_DEBUGOUT("Remote port 0 not allowed\r\n");
		return(-1);
	}
	
	if( dlen > blen )
		dlen = blen;
	
	if( (dlen + UDP_HLEN) > UDP_SEND_MTU)
		dlen = UDP_SEND_MTU - UDP_HLEN;
	
	soc = &udp_socket[sochandle];		/* Get referense	*/

	if(soc->state != UDP_STATE_OPENED ) {
		UDP_DEBUGOUT("UDP Socket Closed\r\n");
		return(-3);
	}
	
	if(soc->locport == 0) {
		UDP_DEBUGOUT("ERROR:Socket local port is zero\r\n");
		return(-1);
	}

	user_buf_start = buf;
	
	buf -= UDP_HLEN;
	
	/* Put header	*/
	
	*buf++ = (UINT8)(soc->locport >> 8);
	*buf++ = (UINT8)soc->locport;
	*buf++ = (UINT8)(remport >> 8);
	*buf++ = (UINT8)remport;
	*buf++ = (UINT8)((dlen + UDP_HLEN) >> 8);
	*buf++ = (UINT8)(dlen + UDP_HLEN);
	*buf++ = 0;
	*buf = 0;
	
	buf = user_buf_start;
	buf -= UDP_HLEN;
	
	/* Calculate checksum if needed	*/
	
	cs = 0;
	
	if( soc->opts & UDP_OPT_SEND_CS) {
		cs = 0;
		cs_cnt = 0;
	
		/* Do it firstly to IP pseudo header	*/
	
		cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 24), cs_cnt++);	
		cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 16), cs_cnt++);
		cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 8), cs_cnt++);
		cs = ip_checksum(cs, (UINT8)localmachine.localip, cs_cnt++);
	
		cs = ip_checksum(cs, (UINT8)(remip >> 24), cs_cnt++);	
		cs = ip_checksum(cs, (UINT8)(remip >> 16), cs_cnt++);
		cs = ip_checksum(cs, (UINT8)(remip >> 8), cs_cnt++);
		cs = ip_checksum(cs, (UINT8)remip, cs_cnt++);	
	
		cs = ip_checksum(cs, 0, cs_cnt++);
	
		cs = ip_checksum(cs, (UINT8)IP_UDP, cs_cnt++);
		
		cs = ip_checksum(cs, (UINT8)((dlen + UDP_HLEN) >> 8), cs_cnt++);
		cs = ip_checksum(cs, (UINT8)(dlen + UDP_HLEN), cs_cnt++);	
	
		/* Go to UDP header + data	*/
	
		buf = user_buf_start;
		buf -= UDP_HLEN;
	
		cs = ip_checksum_buf(cs, buf, dlen + UDP_HLEN);
			
		cs = ~ cs;
	
		if(cs == 0)
			cs = 0xFFFF;
		
		/* Save checksum in correct place	*/
		buf = user_buf_start;
		buf -= UDP_HLEN;
		buf += 6;
		*buf++ = (UINT8)(cs >> 8);
		*buf = (UINT8)cs;	
		
		buf = user_buf_start;
		buf -= UDP_HLEN;
			
	}