/* 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/Ethertap/NetEthertap.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: NetEthertap.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 static void nettapRead(ThreadId dev, unsigned long int length, NetIfDesc *iface); static void nettapDown(ThreadId dev, NetBuf buf, NetAttrs attrs); static void nettap_setaddr(NetAttrs config, char *addr) { unsigned short tmp; netdbgPrintf(NETDEBUG_ETHERTAP, "nettap: hw-address: %02x:%02x:%02x:%02x:%02x:%02x\n", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]); tmp = addr[1]; tmp<<=8; tmp+=addr[0]; netattrSet(config, NETATTR_ETH_FROM_0, tmp); tmp = addr[3]; tmp<<=8; tmp+=addr[2]; netattrSet(config, NETATTR_ETH_FROM_1, tmp); tmp = addr[5]; tmp<<=8; tmp+=addr[4]; netattrSet(config, NETATTR_ETH_FROM_2, tmp); } void nettapMain(NetIfDesc *iface) { ThreadId ethertapMainId, ethertapDeviceId, parentid; NetAttrs config = iface->config; NetModMsg msg; Message *mmsg; char addr[6]; tmGetInfo(SELF, ðertapMainId, &parentid); /* Open/initialize device */ ioOpen(IO_ETHERTAP, ðertapDeviceId); ioInit(ethertapDeviceId); /* Subscribe to Ethertap kernel device driver */ ioSubscribe(ethertapDeviceId, ethertapMainId); /* Get HW address / set attr */ ioGetAddr(ethertapDeviceId, addr, 6); nettap_setaddr(config, addr); /* Add to list of modules */ netmodAdd(NETMODULE_ETHERTAP, ethertapMainId); netdbgDisplay(NETDEBUG_ETHERTAP, "Ethertap module started.\n"); while (1) { if(!netmodMsgRecv(&msg)) return; switch (msg.id) { case IO_NOTIFY: netdbgPrintf(NETDEBUG_ETHERTAP, "nettap: NOTIFY!\n"); mmsg = (Message *) &msg; nettapRead(msg.from, mmsg->msg.ioNotify.length, iface); break; case NETMOD_SENDDOWN: nettapDown(ethertapDeviceId, msg.buf, msg.attrs); break; default: netdbgPrintf(NETDEBUG_ETHERTAP, "nettap: Unknown syscall!\n"); break; } } } static void nettapRead(ThreadId id, unsigned long int length, NetIfDesc *iface) { NetBuf buf; NetAttrs attrs; if (!netbufAlloc(&buf, length+2)) { netdbgDisplay(NETDEBUG_GENERIC, "*** ERROR: Ethertap: netbufAlloc failed.\n"); return; } buf->start+=2; // hack for TCP aligned structure access /* ioOpen isn't needed because threadId is already known... */ ioRead(id, NETBUF_DATA(buf), &length); buf->end = buf->start + length; netdbgPrintf(NETDEBUG_ETHERTAP, "nettap: got %d bytes.\n", length); /* set attributes */ if(!netattrNew(&attrs)) { netdbgDisplay(NETDEBUG_GENERIC, "*** ERROR: Ethertap: netattrNew failed.\n"); netbufFree(buf); return; } netattrSet(attrs, NETATTR_IF_FROM, iface->nr); netcfgSendNextUp(NETMODULE_ETHERTAP, buf, attrs); } static void nettapDown(ThreadId dev, NetBuf buf, NetAttrs attrs) { netdbgPrintf(NETDEBUG_ETHERTAP, "nettap: Sending down packet (len=%d)\n", netbufLen(buf)); netioWrite(dev, buf); netbufFree(buf); netbufFree((NetBuf)attrs); }