/** \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); } }
buf = user_buf_start; buf -= UDP_HLEN; buf += 6; *buf++ = (UINT8)(cs >> 8); *buf = (UINT8)cs; buf = user_buf_start; buf -= UDP_HLEN; } /* Send it to IP */ UDP_DEBUGOUT("Sending UDP...\r\n"); i = process_ip_out(remip, IP_UDP, soc->tos, 100, buf, dlen + UDP_HLEN); /* Errors? */ if( i < 0 ) return(i); UDP_DEBUGOUT("UDP packet sent\r\n"); return(i - UDP_HLEN); }