/*
    NetIP6ModuleDown.c, Copyright  (c) by Jonas Bandi,
    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/IP6/NetIP6ModuleDown.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"
#include "NetIP6Module.h"


void netIP6ModuleDownInit (NetModule this)
{
  netdbgDisplay(NETDEBUG_IP6, "J: netIP6ModuleDownInit \n");

  // XXX what should I do?
  return;
}


int netIP6ModuleDownConfig (NetModule this, Message *msg)
{
  unsigned long	len = msg->msg.netConf.ModuleConf.len;
  unsigned long	i;
  NetAttr			*a = msg->msg.netConf.ModuleConf.attrVec;
  int				exitCode = 0;

  netdbgDisplay(NETDEBUG_IP6, "J: netIP6ModuleDownConfig \n");

  for ( i = 0; i < len ; i++)
  {
    switch ( a[i].key )
    {
      // add all known keys here
    case NETATTR_IP6_MTU:
    case NETATTR_IP6_TRAFFICCLASS:
    case NETATTR_IP6_FLOWLABEL_0:
    case NETATTR_IP6_FLOWLABEL_1:
    case NETATTR_IP6_HOPLIMIT:
    case NETATTR_IP6_SOURCEADDRESS_0:
    case NETATTR_IP6_SOURCEADDRESS_1:
    case NETATTR_IP6_SOURCEADDRESS_2:
    case NETATTR_IP6_SOURCEADDRESS_3:
    case NETATTR_IP6_SOURCEADDRESS_4:
    case NETATTR_IP6_SOURCEADDRESS_5:
    case NETATTR_IP6_SOURCEADDRESS_6:
    case NETATTR_IP6_SOURCEADDRESS_7:
    case NETATTR_IP6_DESTINATIONADDRESS_0:
    case NETATTR_IP6_DESTINATIONADDRESS_1:
    case NETATTR_IP6_DESTINATIONADDRESS_2:
    case NETATTR_IP6_DESTINATIONADDRESS_3:
    case NETATTR_IP6_DESTINATIONADDRESS_4:
    case NETATTR_IP6_DESTINATIONADDRESS_5:
    case NETATTR_IP6_DESTINATIONADDRESS_6:
    case NETATTR_IP6_DESTINATIONADDRESS_7:

      if ( msg->id == NET_CONF_MODULESET )
      {
        // set attributes
        if (! netattrSet(this->attributes, a[i].key, a[i].data) )
        {
          //netdbgPrintf(0, "netmodConfigure: netattrSet failed (%i, %i)\n",a[i].key, a[i].data);
          CONF_FAILEDPLUS(exitCode);
          return exitCode;
        }
        CONF_SUCCEDPLUS(exitCode);
      }
      else if ( msg->id == NET_CONF_MODULEGET )
      {
        if (!netattrGet(this->attributes, a[i].key, &(a[i].data)))
        {
          //netdbgPrintf(0, "netmodConfigure: netattrGet failed (%i)\n",a[i].key);
          CONF_FAILEDPLUS(exitCode);
          return exitCode;
        }
        CONF_SUCCEDPLUS(exitCode);
      }
      else
      {
        //netdbgPrintf(0, "netmodConfigure: AIIEEE, got hit by a bus\n");
        CONF_FAILEDPLUS(exitCode);
        return exitCode;
      }
      break;
    default:
      //netdbgPrintf(0, "netmodConfigure: unknown key %i\n", a[i].key);
      CONF_IGNOREPLUS(exitCode);
    }
  }
  return exitCode;

  return 0;

}


void netIP6ModuleDownMain (LWPool lw, ThreadArg arg)
{

  NetModule		modDesc = (NetModule) arg;
  NetIP6Hdr		*hdr;
  unsigned short	val, payloadlength, ipMTU, hLen;
  NetBuf			data;
  NetAttrs		meta;


  while (1)
  {
    netmodRecv (lw, &data, &meta);
    //netdbgPrintf(NETDEBUG_IP6,"J: netIP6ModuleDownMain: received\n");
    PACKSTART(modDesc);
    payloadlength = htons(netbufLen(data));
    if (netbufAddHeadSpace(&data, sizeof(NetIP6Hdr)) != 1)
    {	// XXX no options right now!
      //netdbgDisplay(NETDEBUG_IP6, "netip6: Failed to allocate header!\n");
      PACKERROR(modDesc);
      netmodRIP (lw, data, meta, "Discarding packet...\n");
      continue;
    }
    hdr = (NetIP6Hdr*) NETBUF_DATA(data);

    // Get MTU
    if (netattrGet (meta, NETATTR_IP6_MTU, &val) )
    {
      ipMTU = val;
    }
    else if (netattrGet (modDesc->attributes, NETATTR_IP_MTU, &val) )
    {
      ipMTU = val;
    }
    else
    {
      //netdbgDisplay(NETDEBUG_IP6, "netip6: Failed to get attribute (MTU)! Setting to default!\n");
      ipMTU = NETIP6_DEFAULT_MTU;
    }
    hdr->bitfield0 = 0;
    // Set IP-Version (6)
    WNIBSET(hdr->bitfield0, 0, 6);
    //hdr->bitfield0 = 0x110<<12;


    // Set traffic class
    if (netattrGet (meta, NETATTR_IP6_TRAFFICCLASS, &val) )
    {
      hdr->bitfield0 = val<<4 | hdr->bitfield0;
    }
    else if (netattrGet (modDesc->attributes, NETATTR_IP6_TRAFFICCLASS , &val) )
    {
      hdr->bitfield0 = val<<4 | hdr->bitfield0;
    }
    else
    {
      //netdbgDisplay(NETDEBUG_IP6, "netip6: Failed to get attribute (TRAFFICCLASS)! Setting to default!\n");
      hdr->bitfield0 = NETIP6_DEFAULT_TRAFFICCLASS<<4 | hdr->bitfield0;
    }

    // Set flow label
    if (netattrGet (meta, NETATTR_IP6_FLOWLABEL_0, &val) )
    {
      hdr->bitfield0 = val<<12 | hdr->bitfield0;
    }
    else if (netattrGet (modDesc->attributes, NETATTR_IP6_FLOWLABEL_0 , &val) )
    {
      hdr->bitfield0 = val<<12 | hdr->bitfield0;
    }
    else
    {
      //netdbgDisplay(NETDEBUG_IP6, "netip6: Failed to get attribute (FLOWLABEL_0)! Setting to default!\n");
      hdr->bitfield0 = NETIP6_DEFAULT_FLOWLABEL_0<<12 |  hdr->bitfield0;
    }
    //hardware adaption
    hdr->bitfield0 = htons(hdr->bitfield0);


    if (netattrGet (meta, NETATTR_IP6_FLOWLABEL_1, &val) )
    {
      hdr->bitfield1 = val;
    }
    else if (netattrGet (modDesc->attributes, NETATTR_IP6_FLOWLABEL_1 , &val) )
    {
      hdr->bitfield1 = val;
    }
    else
    {
      //netdbgDisplay(NETDEBUG_IP6, "netip6: Failed to get attribute (FLOWLABEL_1)! Setting to default!\n");
      hdr->bitfield1 = NETIP6_DEFAULT_FLOWLABEL_1;
    }
    //hardware adaption
    hdr->bitfield1 = htons(hdr->bitfield1);

    // Set payloadlength
    hdr->payloadlength = payloadlength;

    // Set nextheader
    if (netattrGet (meta, NETATTR_IP6_NEXTHEADER, &val) )
    {
      hdr->nextheader = val;
    }
    else if (netattrGet (modDesc->attributes, NETATTR_IP6_NEXTHEADER, &val) )
    {
      hdr->nextheader = val;
    }
    else
    {
      //netdbgDisplay(NETDEBUG_IP6, "netip6: Failed to get attribute (NEXTHEADER)!\n");
      PACKERROR(modDesc);
      netmodRIP (lw, data, meta, "Discarding packet...\n");
      continue;
    }


    // Set hoplimit
    if (netattrGet (meta, NETATTR_IP6_HOPLIMIT, &val) )
    {
      hdr->hoplimit = val;
    }
    else if (netattrGet (modDesc->attributes, NETATTR_IP6_HOPLIMIT , &val) )
    {
      hdr->hoplimit = val;
    }
    else
    {
      //netdbgDisplay(NETDEBUG_IP6, "netip6: Failed to get attribute (HOPLIMIT)! Setting to default!\n");
      hdr->hoplimit = NETIP6_DEFAULT_HOPLIMIT;
    }


    // SETTING ADDRESSES OF OUTGOING PACKET:
    // Check if this is a forwarded packet
    if(!(netattrGet(meta, NETATTR_OSI_4_TYPE, &val) && val == NETATTR_TYPE_IPv4))
    {
      //this is not a forwarded packet
      // Set src address
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_0, &val) )
      {
        hdr->saddr0 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_0, &val) )
      {
        hdr->saddr0 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_0)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }

      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_1, &val) )
      {
        hdr->saddr1 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_1, &val) )
      {
        hdr->saddr1 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_1)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_2, &val) )
      {
        hdr->saddr2 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_2, &val) )
      {
        hdr->saddr2 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_3)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_3, &val) )
      {
        hdr->saddr3 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_3, &val) )
      {
        hdr->saddr3 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_3)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_4, &val) )
      {
        hdr->saddr4 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_4, &val) )
      {
        hdr->saddr4 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_4)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_5, &val) )
      {
        hdr->saddr5 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_5, &val) )
      {
        hdr->saddr5 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_5)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_6, &val) )
      {
        hdr->saddr6 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_6, &val) )
      {
        hdr->saddr6 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_6)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_7, &val) )
      {
        hdr->saddr7 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_7, &val) )
      {
        hdr->saddr7 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_7)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }


      // Set dest address

      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_0, &val) )
      {
        hdr->daddr0 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_0, &val) )
      {
        hdr->daddr0 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_0)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_1, &val) )
      {
        hdr->daddr1 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_1, &val) )
      {
        hdr->daddr1 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_1)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_2, &val) )
      {
        hdr->daddr2 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_2, &val) )
      {
        hdr->daddr2 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_2)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_3, &val) )
      {
        hdr->daddr3 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_3, &val) )
      {
        hdr->daddr3 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_3)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_4, &val) )
      {
        hdr->daddr4 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_4, &val) )
      {
        hdr->daddr4 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_4)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_5, &val) )
      {
        hdr->daddr5 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_5, &val) )
      {
        hdr->daddr5 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_5)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_6, &val) )
      {
        hdr->daddr6 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_6, &val) )
      {
        hdr->daddr6 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_6)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_7, &val) )
      {
        hdr->daddr7 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_7, &val) )
      {
        hdr->daddr7 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_7)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
    }
    else
    {
      // this is a forwarded packet

      // Set src address
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_0, &val) )
      {
        hdr->saddr0 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_0, &val) )
      {
        hdr->saddr0 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_0)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }

      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_1, &val) )
      {
        hdr->saddr1 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_1, &val) )
      {
        hdr->saddr1 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_1)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }

      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_2, &val) )
      {
        hdr->saddr2 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_2, &val) )
      {
        hdr->saddr2 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_3)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_3, &val) )
      {
        hdr->saddr3 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_3, &val) )
      {
        hdr->saddr3 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_3)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_4, &val) )
      {
        hdr->saddr4 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_4, &val) )
      {
        hdr->saddr4 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_4)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_5, &val) )
      {
        hdr->saddr5 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_5, &val) )
      {
        hdr->saddr5 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_5)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_6, &val) )
      {
        hdr->saddr6 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_6, &val) )
      {
        hdr->saddr6 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_6)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_DESTINATIONADDRESS_7, &val) )
      {
        hdr->saddr7 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_DESTINATIONADDRESS_7, &val) )
      {
        hdr->saddr7 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_DESTINATIONADDRESS_7)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      // set dest addr
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_0, &val) )
      {
        hdr->daddr0 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_0, &val) )
      {
        hdr->daddr0 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_0)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_1, &val) )
      {
        hdr->daddr1 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_1, &val) )
      {
        hdr->daddr1 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_1)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_2, &val) )
      {
        hdr->daddr2 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_2, &val) )
      {
        hdr->daddr2 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_2)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_3, &val) )
      {
        hdr->daddr3 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_3, &val) )
      {
        hdr->daddr3 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_3)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_4, &val) )
      {
        hdr->daddr4 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_4, &val) )
      {
        hdr->daddr4 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_4)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_5, &val) )
      {
        hdr->daddr5 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_5, &val) )
      {
        hdr->daddr5 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_5)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_6, &val) )
      {
        hdr->daddr6 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_6, &val) )
      {
        hdr->daddr6 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_6)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
      if (netattrGet (meta, NETATTR_IP6_SOURCEADDRESS_7, &val) )
      {
        hdr->daddr7 = val;
      }
      else if (netattrGet (modDesc->attributes, NETATTR_IP6_SOURCEADDRESS_7, &val) )
      {
        hdr->daddr7 = val;
      }
      else
      {
        //netdbgDisplay(NETDEBUG_IP6, "netip: Failed to get attribute (NETATTR_IP6_SOURCEADDRESS_7)!\n");
        PACKERROR(modDesc);
        netmodRIP (lw, data, meta, "Discarding packet...\n");
        continue;
      }
    }

    //hardware adaption
    hdr->saddr0 = htons(hdr->saddr0);
    hdr->saddr1 = htons(hdr->saddr1);
    hdr->saddr2 = htons(hdr->saddr2);
    hdr->saddr3 = htons(hdr->saddr3);
    hdr->saddr4 = htons(hdr->saddr4);
    hdr->saddr5 = htons(hdr->saddr5);
    hdr->saddr6 = htons(hdr->saddr6);
    hdr->saddr7 = htons(hdr->saddr7);

    hdr->daddr0 = htons(hdr->daddr0);
    hdr->daddr1 = htons(hdr->daddr1);
    hdr->daddr2 = htons(hdr->daddr2);
    hdr->daddr3 = htons(hdr->daddr3);
    hdr->daddr4 = htons(hdr->daddr4);
    hdr->daddr5 = htons(hdr->daddr5);
    hdr->daddr6 = htons(hdr->daddr6);
    hdr->daddr7 = htons(hdr->daddr7);

    // Have to let the lower level know that this is an IP-packet
    netattrSet (meta, NETATTR_ETH_TYPE, NETETH_TYPE_IP);

    //netdbgDisplay(NETDEBUG_IP6, "NetIP6ModuleDown: sending packet do next module\n");

    // Finished: send the packet
    PACKDONE(modDesc);
    netmodSend (lw, CHAINNEXT(modDesc), data, meta);
  }

}
