/* 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/Ethernet/NetEthernet.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: NetEthernet.c,v $ Revision 1.1 2000/03/31 17:50:36 gfa Merged with /Net from several term projects */ #include #include #include #include #include #include #include #include #include #include #include void netethRead(ThreadId id, unsigned long int length); static void netethMain(ThreadArg arg); static void netethUp(NetBuf buf, NetAttrs attrs); static void netethDown(NetBuf buf, NetAttrs attrs); /* cache of hw address of ethernet interfaces */ unsigned short neteth_hwaddr_cache[NETIF_IFCOUNT][3]; unsigned char neteth_hwaddr_cache_set[NETIF_IFCOUNT]; void netethInit() { ThreadId netethId; int i; for(i=0; idest[0],hdr->dest[1],hdr->dest[2], hdr->dest[3],hdr->dest[4],hdr->dest[5]); netdbgPrintf(NETDEBUG_ETHERNET, ", src = %02x:%02x:%02x:%02x:%02x:%02x", hdr->src[0],hdr->src[1],hdr->src[2], hdr->src[3],hdr->src[4],hdr->src[5]); netdbgPrintf(NETDEBUG_ETHERNET, ", type = %04x\n", ntohs(hdr->type)); /* we work with shorts ... */ to[0] =hdr->dest[1]; to[0] <<=8; to[0] |=hdr->dest[0]; to[1] =hdr->dest[3]; to[1] <<=8; to[1] |=hdr->dest[2]; to[2] =hdr->dest[5]; to[2] <<=8; to[2] |=hdr->dest[4]; from[0]=hdr->src[1]; from[0]<<=8; from[0]|=hdr->src[0]; from[1]=hdr->src[3]; from[1]<<=8; from[1]|=hdr->src[2]; from[2]=hdr->src[5]; from[2]<<=8; from[2]|=hdr->src[4]; /* was a broadcast? */ for(i=0; i<3; i++) if(to[i]!=0xFFFF) break; if(i<3) { /* ... no (it isn't a broadcast) */ /* check address */ /* Get originating iface */ netattrGet(attrs, NETATTR_IF_FROM, &iface); /* cache hw address of iface */ if(!netethCacheAddr(iface)) goto discard; netdbgPrintf(NETDEBUG_ETHERNET, "neteth: checking address: to[0]=%d, cache[iface][0]=%d\n", to[0], neteth_hwaddr_cache[iface][0]); netdbgPrintf(NETDEBUG_ETHERNET, "neteth: checking address: to[1]=%d, cache[iface][1]=%d\n", to[1], neteth_hwaddr_cache[iface][1]); netdbgPrintf(NETDEBUG_ETHERNET, "neteth: checking address: to[2]=%d, cache[iface][2]=%d\n", to[2], neteth_hwaddr_cache[iface][2]); /* check address */ if((to[0] != neteth_hwaddr_cache[iface][0]) || (to[1] != neteth_hwaddr_cache[iface][1]) || (to[2] != neteth_hwaddr_cache[iface][2])) goto discard; } /* Set attributes */ netattrSet(attrs, NETATTR_ETH_FROM_0, from[0]); netattrSet(attrs, NETATTR_ETH_FROM_1, from[1]); netattrSet(attrs, NETATTR_ETH_FROM_2, from[2]); netattrSet(attrs, NETATTR_ETH_TO_0, to[0]); netattrSet(attrs, NETATTR_ETH_TO_1, to[1]); netattrSet(attrs, NETATTR_ETH_TO_2, to[2]); netattrSet(attrs, NETATTR_ETH_TYPE, ntohs(hdr->type)); netdbgPrintf(NETDEBUG_ETHERNET, "neteth: Packet type: %04x\n", ntohs(hdr->type)); /* Remove header */ buf->start += 14; /* Send up packet */ netdbgDisplay(NETDEBUG_ETHERNET, "neteth: Sending up packet.\n"); netcfgSendNextUp(NETMODULE_ETHERNET, buf, attrs); return; discard: netdbgDisplay(NETDEBUG_ETHERNET, "neteth: Discarding upcoming packet.\n"); netbufFree(buf); netattrFree(attrs); } /* required attributes for a downgoing packet: * NETATTR_ETH_TO_0 * NETATTR_ETH_TO_1 * NETATTR_ETH_TO_2 * NETATTR_ETH_TYPE * NETATTR_IF_TO * */ static void netethDown(NetBuf buf, NetAttrs attrs) { NetEthernetHdr hdr; unsigned short data,iface; /*netdbgDumpBuf(NETDEBUG_ETHERNET, buf);*/ /* add ethernet header */ netbufAddHead(&buf, sizeof(struct NetEthernetHdr_t)); /* fill in data */ hdr = (NetEthernetHdr) NETBUF_DATA(buf); /* netattrDebug(NETDEBUG_ETHERNET, "netethDown", attrs); */ /* set destination address */ /* if(!netattrGet(attrs, NETATTR_ETH_TO_0, &data)) goto error; hdr->dest[0]=data%256; hdr->dest[1]=data>>8; if(!netattrGet(attrs, NETATTR_ETH_TO_1, &data)) goto error; hdr->dest[2]=data%256; hdr->dest[3]=data>>8; if(!netattrGet(attrs, NETATTR_ETH_TO_2, &data)) goto error; hdr->dest[4]=data%256; hdr->dest[5]=data>>8; */ if(!netattrGet(attrs, NETATTR_ETH_TO_0, &data)) goto error; hdr->dest[1]=data%256; //swapped RGA hdr->dest[0]=data>>8; if(!netattrGet(attrs, NETATTR_ETH_TO_1, &data)) goto error; hdr->dest[3]=data%256; hdr->dest[2]=data>>8; if(!netattrGet(attrs, NETATTR_ETH_TO_2, &data)) goto error; hdr->dest[5]=data%256; hdr->dest[4]=data>>8; /* set source address */ if(!netattrGet(attrs, NETATTR_IF_TO, &iface)) goto error; if(!netethCacheAddr(iface)) goto error; hdr->src[0]=neteth_hwaddr_cache[iface][0]%256; hdr->src[1]=neteth_hwaddr_cache[iface][0]>>8; hdr->src[2]=neteth_hwaddr_cache[iface][1]%256; hdr->src[3]=neteth_hwaddr_cache[iface][1]>>8; hdr->src[4]=neteth_hwaddr_cache[iface][2]%256; hdr->src[5]=neteth_hwaddr_cache[iface][2]>>8; /* set type */ if(!netattrGet(attrs,NETATTR_ETH_TYPE,&data)) goto error; hdr->type=htons(data); /* send down */ netcfgSendNextDown(NETMODULE_ETHERNET, buf, attrs); return; /* these gotos can be seen as a ugly practice, but I use them like as a convenient and clean way of doing exceptions handling */ error: netdbgDisplay(NETDEBUG_ETHERNET, "neteth: Discarding downgoing packet.\n"); netbufFree(buf); netbufFree((NetBuf)attrs); }