/*
    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: /home/ruf/cvs_Topsy/cvs/Topsy/Net/old/NetConfig.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 $
 
 
    $Log: NetConfig.c,v $
    Revision 1.3  2001/01/23 09:43:31  cjeker
    moved to Net/old
 
    Revision 1.2  2000/11/15 10:12:14  ruf
    Repository Reorganisation
 
    Revision 1.1  2000/03/31 17:50:33  gfa
    Merged with /Net from several term projects
 
*/
/* NetConfig.c: dirty stuff between modules */

#include <NetDebug.h>
#include <NetConfig.h>
#include <Ethernet/NetEthernet.h>
#include <IP/NetIP.h>
#include <NetConfigARP.h>

NetModuleId netcfgNextUpEth(NetModuleId from, NetAttrs attr);
NetModuleId netcfgNextUpIP(NetModuleId from, NetAttrs attr);

/* static netcfglock; */

void netcfgInit()
{
  netcfgarpInit();
}



/************ UP ***********/

/* netcfgNextUp: get next module in path to receive packet (interface -> user) */
NetModuleId netcfgNextUp(NetModuleId from, NetAttrs attr)
{
  NetModuleId next=0;

  switch(from)
  {
  case NETMODULE_ETHERTAP:
    next=NETMODULE_ETHERNET;
    break;
  case NETMODULE_ETHERNET:
    next=netcfgNextUpEth(from,attr);
    break;
  case NETMODULE_IP:
    next=netcfgNextUpIP(from,attr);
    break;
  default:
    netdbgDisplay(NETDEBUG_GENERIC, "netcfg: Unknown module.\n");
    break;
  }
  netdbgPrintf(NETDEBUG_CONFIG, "netcfg: sending up packet from> %d to: %d\n",from,next);

  return next;
}

int netcfgTransformUp(NetModuleId from, NetModuleId to, NetBuf buf, NetAttrs attrs)
{
  return 1; /* always send */
}

/* netcfgSendNextUp: combined netcfgTransformUp+netcfgNextUp+netmodSendUp. */
int netcfgSendNextUp(NetModuleId from, NetBuf buf, NetAttrs attrs)
{
  NetModuleId to;

  netdbgPrintf(NETDEBUG_GENERIC, "netcfg: start=%p\n", NETBUF_DATA(buf));

  to = netcfgNextUp(from, attrs);
  if(!to)
    goto discard;
  if(!netcfgTransformUp(from, to, buf, attrs))
    return 0;
  netmodSendUp(to,buf,attrs);
  return 1;

discard:
  netdbgDisplay(NETDEBUG_CONFIG, "netcfg: Discarding upcoming packet.\n");
  netbufFree(buf);
  NETATTR_FREE(attrs);
  return 0;
}



/******** DOWN ********/

/* netcfgNextSend: get next module in path to send packet (user -> interface) */
NetModuleId netcfgNextDown(NetModuleId from, NetAttrs attr)
{
  NetModuleId next=0;

  switch(from)
  {
  case NETMODULE_ETHERNET:
    next=NETMODULE_ETHERTAP;
    break;
  case NETMODULE_ARP:
    next=NETMODULE_ETHERNET;
    break;
  case NETMODULE_IP:
    next=NETMODULE_ETHERNET;
    /* else              next=NETMODULE_SENDBACK; */
    break;
  case NETMODULE_ICMP:
    next=NETMODULE_IP;
    break;
  case NETMODULE_UDP:
    next=NETMODULE_IP;
    break;
  case NETMODULE_TCP_OUT:
    next=NETMODULE_IP;
    break;
  default:
    netdbgDisplay(NETDEBUG_GENERIC, "netcfg: Unknown module.\n");
    break;
  }
  return next;
}

NetModuleId netcfgNextUpEth(NetModuleId from, NetAttrs attr)
{
  unsigned short type;

  if(!netattrGet(attr, NETATTR_ETH_TYPE, &type))
    return 0;

  switch(type)
  {
  case NETETH_TYPE_ARP:
    return NETMODULE_ARP;
  case NETETH_TYPE_IP:
    return NETMODULE_IP;
  default:
    return 0;
  }
}

NetModuleId netcfgNextUpIP(NetModuleId from, NetAttrs attr)
{
  unsigned short protocol;

  if(!netattrGet(attr, NETATTR_IP_PROTOCOL, &protocol))
    return 0;

  switch(protocol)
  {
  case NETIP_PROTOCOL_ICMP:
    return NETMODULE_ICMP;
  case NETIP_PROTOCOL_UDP:
    return NETMODULE_UDP;
  case NETIP_PROTOCOL_TCP:
    return NETMODULE_TCP_IN;
  default:
    return 0;
  }
}

/* netcfgTransformDown: do for example the ARP stuff. return 0 if the packet
 * shouldn't be freed or sent (set on hold for example) */
int netcfgTransformDown(NetModuleId from, NetModuleId to, NetBuf buf, NetAttrs attrs)
{
  if(from==NETMODULE_IP && to==NETMODULE_ETHERNET)
  {
    /* Set ethernet packet type */
    netattrSet(attrs,NETATTR_ETH_TYPE,NETETH_TYPE_IP);
    /* do the ARP stuff */
    return netcfgarpResolveETHIP(buf,attrs);
  }

  return 1;
}

/* netcfgSendNextDown: combined netcfgTransformDown+netcfgNextDown+netmodSendDown. */
int netcfgSendNextDown(NetModuleId from, NetBuf buf, NetAttrs attrs)
{
  NetModuleId to;

  to = netcfgNextDown(from, attrs);
  if(!to)
    goto discard;
  if(!netcfgTransformDown(from, to, buf, attrs))
    return 0;
  netdbgPrintf(NETDEBUG_CONFIG, "netcfg: sending down packet from: %d to: %d\n",from,to);
  netmodSendDown(to,buf,attrs);
  return 1;

discard:
  netdbgDisplay(NETDEBUG_CONFIG, "netcfg: Discarding downgoing packet.\n");
  netbufFree(buf);
  NETATTR_FREE(attrs);
  return 0;
}

