/*
    NetEthernetModuleUp.c, Copyright  (c) by Boris Lutz,
    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: /home/ruf/cvs_Topsy/cvs/Topsy/Net/Modules/Ethernet/NetEthernetModuleUp.c,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/
#include "NetModulesNew.h"
#include "NetAttr.h"
#include "LWThreads.h"
#include "NetBitFields.h"
#include "NetByteorder.h"
#include "NetDebug.h"
#include "NetEthernetModule.h"


void netEthernetModuleUpInit (NetModule this)
{
  /* XXX what should I do? */
  return;
}


int netEthernetModuleUpConfig (NetModule this, Message *msg)
{
  return 0;
}


void netEthernetModuleUpMain (LWPool lw, ThreadArg arg)
{
  NetModule			modDesc = (NetModule) arg;
  NetEthernetHdr		*hdr;
  unsigned short		to[3],
  from[3];
  NetBuf				data;
  NetAttrs			meta;


  while (1)
  {
    netmodRecv (lw, &data, &meta);
    PACKSTART(modDesc);
    netdbgPrintf(NETDEBUG_IP6, "netEthernet: netEthernetModuleUpMain receiving ----------------------->\n");
    hdr = (NetEthernetHdr*) NETBUF_DATA(data);

    // We work with shorts (ethernet header works with u8)
    to[0]  =hdr->dest[0];
    to[0] <<=8;
    to[0]  |=hdr->dest[1];
    to[1]  =hdr->dest[2];
    to[1] <<=8;
    to[1]  |=hdr->dest[3];
    to[2]  =hdr->dest[4];
    to[2] <<=8;
    to[2]  |=hdr->dest[5];
    from[0]=hdr->src[0];
    from[0]<<=8;
    from[0]|=hdr->src[1];
    from[1]=hdr->src[2];
    from[1]<<=8;
    from[1]|=hdr->src[3];
    from[2]=hdr->src[4];
    from[2]<<=8;
    from[2]|=hdr->src[5];

    /* XXX Broadcasts and packets not addressed to us will
       be accepted anyway right now (this might be useful
       for sniffers and modules on higher levels) XXX */

    if (!(
          /* Set local address */
          netattrSet(meta, NETATTR_ETH_LOCAL_0, to[0]) &&
          netattrSet(meta, NETATTR_ETH_LOCAL_1, to[1]) &&
          netattrSet(meta, NETATTR_ETH_LOCAL_2, to[2]) &&
          /* Set remote address */
          netattrSet(meta, NETATTR_ETH_REMOTE_0, from[0]) &&
          netattrSet(meta, NETATTR_ETH_REMOTE_1, from[1]) &&
          netattrSet(meta, NETATTR_ETH_REMOTE_2, from[2]) &&
          /* Set type */
          netattrSet(meta, NETATTR_ETH_TYPE, ntohs(hdr->type))
        ) )
    {
      goto fail;
    }


    switch ( ntohs(hdr->type) )
    {
    case NETETH_TYPE_IP:
      if (! netattrSet(meta, NETATTR_OSI_3_TYPE, NETATTR_TYPE_IPv4) )
        goto fail;
      break;
    case NETETH_TYPE_IPv6:
      if (! netattrSet(meta, NETATTR_OSI_3_TYPE, NETATTR_TYPE_IPv6) )
        goto fail;
      break;
    case NETETH_TYPE_ARP:
      if (! netattrSet(meta, NETATTR_OSI_3_TYPE, NETATTR_TYPE_ARP) )
        goto fail;
      break;
    default:
      PACKERROR(modDesc);
      netmodRIP(lw, data, meta, "unknown ethernet type\n");
      continue;
    }

    // Strip header
    data->start += 14;
    // Finished: send it on...
    PACKDONE(modDesc);
    netmodSend (lw, CHAINNEXT(modDesc), data, meta);
    continue;

fail:
    PACKERROR(modDesc);
    netmodRIP(lw, data, meta, "netEthernetUp: failed to set attributes\n");
    continue;
  }
}
