/*
    NullModule.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/IP/NetIPDummyRoute.c,v $
    Author(s):
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Creation Date:
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/
#include "Topsy.h"
#include "Syscall.h"
#include "Support.h"
#include "NetModulesNew.h"
#include "NetAttr.h"
#include "LWThreads.h"
#include "NetHAL.h"
#include "NetDebug.h"


void netIPDummyRouteInit(NetModule this)
{
  return;
}


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


void netIPDummyRouteMain(LWPool lw, ThreadArg arg)
{
  NetModule		modDesc = (NetModule) arg;
  NetBuf			data;
  NetAttrs		meta;
  u16				type, devNr, ttl, v1, v2, ifto;


  while (1)
  {
    netmodRecv(lw, &data, &meta);
    PACKSTART(modDesc);

    if (!netattrGet(meta, NETATTR_OSI_3_TYPE, &type) )
    {
      PACKERROR(modDesc);
      netmodRIP(lw, data, meta, "IPRoute: failed to get type\n");
      continue;
    }
    switch(type)
    {
    case NETATTR_TYPE_IPv4:
      netdbgPrintf(NETDEBUG_IP6, "netIPForwardig: forwarding an IPv4 packet.\n");
      if (!netattrGet(meta, NETATTR_IP_LOCAL_2, &type) )
      {
        PACKERROR(modDesc);
        netmodRIP(lw, data, meta, "IPRoute: failed to make route decision\n");
        continue;
      }
      if ( type > 3 || type == 0 )
      {
        type = 1;
      }
      if (!netattrGet(meta, NETATTR_IP_TTL, &ttl) )
      {
        PACKERROR(modDesc);
        netmodRIP(lw, data, meta, "IPRoute: failed to get TTL\n");
        continue;
      }
      if ( ttl == 0 )
      {
        PACKERROR(modDesc);
        netmodRIP(lw, data, meta, "IPRoute: TTL expired packet killed\n");
        continue;

      }
      ttl--;
      //-CJ printf("****IPRoute: set IF_TO = %i, TTL = %i\n", type-1, ttl);
      if (netattrSet(meta, NETATTR_IF_TO, type-1) &&
          netattrSet(meta, NETATTR_IP_TTL, ttl) &&
          netattrGet(meta, NETATTR_IP_LOCAL_0, &v1) &&
          netattrGet(meta, NETATTR_IP_REMOTE_0, &v2) &&
          netattrSet(meta, NETATTR_IP_LOCAL_0, v2) &&
          netattrSet(meta, NETATTR_IP_REMOTE_0, v1) &&
          netattrGet(meta, NETATTR_IP_LOCAL_1, &v1) &&
          netattrGet(meta, NETATTR_IP_REMOTE_1, &v2) &&
          netattrSet(meta, NETATTR_IP_LOCAL_1, v2) &&
          netattrSet(meta, NETATTR_IP_REMOTE_1, v1) &&
          netattrGet(meta, NETATTR_IP_LOCAL_2, &v1) &&
          netattrGet(meta, NETATTR_IP_REMOTE_2, &v2) &&
          netattrSet(meta, NETATTR_IP_LOCAL_2, v2) &&
          netattrSet(meta, NETATTR_IP_REMOTE_2, v1) &&
          netattrGet(meta, NETATTR_IP_LOCAL_3, &v1) &&
          netattrGet(meta, NETATTR_IP_REMOTE_3, &v2) &&
          netattrSet(meta, NETATTR_IP_LOCAL_3, v2) &&
          netattrSet(meta, NETATTR_IP_REMOTE_3, v1) &&
          netattrSet(meta, NETATTR_OSI_2_TYPE, NETATTR_TYPE_ETHERNET) &&
          netattrSet(meta, NETATTR_OSI_3_TYPE, NETATTR_TYPE_IPv4) )
      {
        PACKDONE(modDesc);
        netmodSend(lw, CHAINNEXT(modDesc), data, meta);
        continue;
      }
      PACKERROR(modDesc);
      netmodRIP(lw, data, meta, "IPRoute: can not set attributes\n");
      break;


    case NETATTR_TYPE_IPv6:
      if (!netattrGet(meta, NETATTR_IF_FROM, &v1) )
      {
        PACKERROR(modDesc);
        netmodRIP(lw, data, meta, "IPRoute: failed to get TTL\n");
        continue;
      }
      //(jb) for the presentation: forwarding 0->1 and 1->0
      if(v1 == 0)
      {
        ifto = 1;
      }
      else
      {
        ifto = 0;
      }

      //(jb) handle hoplimit (ttl)
      if (!netattrGet(meta, NETATTR_IP6_HOPLIMIT, &ttl) )
      {
        PACKERROR(modDesc);
        netmodRIP(lw, data, meta, "IPRoute: failed to get HOPLIMIT\n");
        continue;
      }
      if ( ttl == 0 )
      {
        PACKERROR(modDesc);
        netmodRIP(lw, data, meta, "IPRoute: HOPLIMIT expired packet killed\n");
        continue;

      }
      ttl--;


      netdbgPrintf(NETDEBUG_IP6, "netIPForwardig: forwarding an IPv6 packet: IF:%d -> IF:%d\n",v1,ifto);
      if (netattrSet(meta, NETATTR_IF_TO, ifto) &&
          netattrSet(meta, NETATTR_IP6_HOPLIMIT, ttl) &&
          netattrSet(meta, NETATTR_OSI_2_TYPE, NETATTR_TYPE_ETHERNET) &&
          netattrSet(meta, NETATTR_OSI_3_TYPE, NETATTR_TYPE_IPv6)
         )
      {
        PACKDONE(modDesc);
        netmodSend(lw, CHAINNEXT(modDesc), data, meta);
        continue;
      }
      PACKERROR(modDesc);
      netmodRIP(lw, data, meta, "IPRoute: can not set attributes\n");
      break;


    default:
      PACKERROR(modDesc);
      netmodRIP(lw, data, meta, "IPRoute: unkown type\n");
      continue;

    }
  }
}


