/* Copyright 2000 (c) by David Schweikert, Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. TOPSY -- A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. For further information, please visit http://www.tik.ee.ethz.ch/~topsy This software is provided under the terms of the GNU General Public Licence. A full copy of the GNU GPL is provided in the file COPYING found in the development root of Topsy. */ /* File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/Net/ICMP/NetICMP.c,v $ Author(s): Affiliation: ETH Zuerich, TIK Version: $Revision: 1.1 $ Creation Date: Last Date of Change: $Date: 2000/03/31 17:50:36 $ by: $Author: gfa $ $Log: NetICMP.c,v $ Revision 1.1 2000/03/31 17:50:36 gfa Merged with /Net from several term projects */ #include "NetICMP.h" #include #include #include #include #include #include #include #include #include #include #include void neticmpRead(ThreadId id, unsigned long int length); static void neticmpMain(ThreadArg arg); static void neticmpUp(NetBuf buf, NetAttrs attrs); static void neticmpDown(NetBuf buf, NetAttrs attrs); void neticmpInit() { ThreadId neticmpId; /* Start main thread */ if (tmStart(&neticmpId, neticmpMain, (ThreadArg)0, "neticmp") != TM_STARTOK) { netdbgDisplay(NETDEBUG_GENERIC, "Start: couldn't start ICMP thread\n"); return; } } static void neticmpMain(ThreadArg arg) { ThreadId myThreadId, parentThreadId; NetModMsg msg; tmGetInfo(SELF, &myThreadId, &parentThreadId); // Add to list of modules netmodAdd(NETMODULE_ICMP, myThreadId); netdbgPrintf(NETDEBUG_MODULES, "ICMP module started (moduleId=%d, threadId=%d).\n", NETMODULE_ICMP, myThreadId); while(1) { if(!netmodMsgRecv(&msg)) return; switch (msg.id) { case NETMOD_SENDUP: neticmpUp(msg.buf, msg.attrs); break; case NETMOD_SENDDOWN: neticmpDown(msg.buf, msg.attrs); break; default: netdbgPrintf(NETDEBUG_GENERIC, "*** ERROR: ICMP: Unknown message (%d)!\n", msg.id); break; } } } static void neticmpEchoUp(NetBuf buf, NetAttrs attrs) { NetICMPHdr hdr=(NetICMPHdr) NETBUF_DATA(buf); NetAttrs newattrs=0; unsigned short tmp; netdbgDisplay(NETDEBUG_ICMP, "neticmp: Got ECHO REQUEST.\n"); /* We resend exactly the same data to the sender. */ /* Only 'type' is changed from ECHO to ECHOREPLY */ hdr->type = NETICMP_TYPE_ECHOREPLY; /* We rebuild the attributes for the down-going packet */ if(!netattrNew(&newattrs)) goto error; /* Determine sender and set destination to the same. */ if(!netattrGet(attrs, NETATTR_IP_FROM_0, &tmp)) goto error; netattrSet(newattrs, NETATTR_IP_TO_0, tmp); if(!netattrGet(attrs, NETATTR_IP_FROM_1, &tmp)) goto error; netattrSet(newattrs, NETATTR_IP_TO_1, tmp); if(!netattrGet(attrs, NETATTR_IP_FROM_2, &tmp)) goto error; netattrSet(newattrs, NETATTR_IP_TO_2, tmp); if(!netattrGet(attrs, NETATTR_IP_FROM_3, &tmp)) goto error; netattrSet(newattrs, NETATTR_IP_TO_3, tmp); /* 'Protocol' for IP is ICMP */ netattrSet(newattrs, NETATTR_IP_PROTOCOL, NETIP_PROTOCOL_ICMP); /* Re-calculate checksum (see RFC 1141) */ /* ~C' = ~(C + (-m) + m') = ~C + (m - m') = ~C + m + ~m' */ hdr->checksum+=NETICMP_TYPE_ECHO + ~(NETICMP_TYPE_ECHOREPLY); //hdr->checksum=htons(netipChecksum(buf,netbufLen(buf))); /* Send down the reply packet */ netdbgDisplay(NETDEBUG_ICMP, "neticmp: Sending ECHO REPLY.\n"); netcfgSendNextDown(NETMODULE_ICMP, buf, newattrs); /* Free the old attributes */ netattrFree(attrs); return; error: netdbgDisplay(NETDEBUG_ICMP, "neticmp: Discarding packet.\n"); if(newattrs) netattrFree(newattrs); netattrFree(attrs); netbufFree(buf); } static void neticmpUp(NetBuf buf, NetAttrs attrs) { NetICMPHdr hdr=(NetICMPHdr) NETBUF_DATA(buf); int len = netbufLen(buf); /* Process packet and fill attrs */ netdbgPrintf(NETDEBUG_ICMP, "neticmp: Got packet (len=%d).\n",NETBUF_LEN(buf)); /* Check length */ if(len<4) goto discard; /* Check checksum */ if(netipChecksum(buf,netbufLen(buf))) { netdbgPrintf(NETDEBUG_GENERIC, "neticmp: Checkum error!\n"); goto discard; } switch(hdr->type) { case NETICMP_TYPE_ECHO: neticmpEchoUp(buf,attrs); break; default: goto discard; } return; discard: netdbgDisplay(NETDEBUG_ICMP, "neticmp: Discarding packet.\n"); netbufFree(buf); netbufFree((NetBuf)attrs); } static void neticmpDown(NetBuf buf, NetAttrs attrs) { /* Build header and fill attrs */ /* Send down packet */ netcfgSendNextDown(NETMODULE_ICMP, buf, attrs); }