/*
    Copyright 2000 (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/NetAutoConfiguration.c,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2936 $
    Last Date of Change:   $Date: 2007-03-21 15:23:42 +0100 (Mit, 21 Mär 2007) $  by: $Author: baderma $
 
*/


#include "Topsy.h"
#include "IODevice.h"
#include "Syscall.h"
#include "Support.h"
#include "NetByteorder.h"
#include "NetDevice.h"
#include "NetError.h"
#include "NetConfigMngr.h"
#include "NetARP.h"
#include "NetDebug.h"
#include "Socket.h"
#include "NetSocket.h"
#include "TMTimerNG.h"
#include "TMTime.h"
#include "NetAutoConfiguration.h"
#include "NetMemoryManager.h"
//#include "NetAppli.h"


u8						gatesOfHell[4];		// Gateway address


void netAutoConfiguration (ThreadId arg)
{
  int								nextState = 0,
  									notQuit = 0,
  									i = 0,
  									myDevice = 0,
  									defaultDevice = 0,
  									moreDevToConfig = 0,
  									configuredDefaultDevice = 0;
  //ThreadId							mySock,
  ThreadId							from;
  Message							msg,
  									reply;
  NetAutoConfigurationHdr			Reply;
  NetAutoConfigurationHdr           myRequest;
  u8								myHWAddress[6];		// for ethernet

  char                              stringsend[20];
  char*  							buffer = NULL;
  int    							blen = 0;

  long			                	len = 0;

  long								sId = 999,			// XXX should be random
  									hwLen = 0;
  NetAttr							*myAddrAttr;
  //NetAttr                           *mySockAttr;
  u16                               proto, device;
  NetDevice		                	d;
  unsigned short	              	val[8], deviceNr;
  u8                                pa[17], arp_pa[16];
  u8                                ha[7];
  u8                                pa_len;

  extern ThreadId                 	arp_main_thread;
  extern ThreadId					netConfigThread;
  extern ThreadId					net_appli_thread;


  blen = 30;
  buffer = "UDP over IPV6";

  defaultDevice = 0;
  myDevice = defaultDevice;
  configuredDefaultDevice = FALSE;
  moreDevToConfig = TRUE;

  vmAlloc ((Address*) &(myAddrAttr), sizeof(NetAttr) * 14);	// should be big enough

  // Configure all devices...
  while (moreDevToConfig)
  {
    //moreDevToConfig = FALSE;
    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: starting to config device %d\n", myDevice);

    // make sure that the default devices has been configured before
    // trying to configure other devices via the default devoce
    if (myDevice > defaultDevice && configuredDefaultDevice == FALSE)
    {
      printf ("NetAutoConfiguration: failed to configure default Device! Can't configure other devices, exiting...\n");
      //vmFree (mySockAttr);
      vmFree (myAddrAttr);
      tmExit();
    }
    // init states for AutoConfiguration
    notQuit = TRUE;
    //nextState = STATE_STARTED;
    nextState = STATE_ARP_FILL;


    // get myHWAddress
    msg.id = NET_CONF_GETHWADDR;
    msg.msg.netConf.HWAddrGet.deviceNr = myDevice;
    msg.msg.netConf.HWAddrGet.attrVec = myAddrAttr;
    hwLen = 10;
    msg.msg.netConf.HWAddrGet.len = &hwLen;

    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: Sending to netConfigThread for device %d\n", myDevice);


    if (tmMsgSend (netConfigThread, &msg) != TM_MSGSENDOK)
    {
      printf ("NetAutoConfiguration: failed to get hwaddress (tmMsgSend)!\n");
      vmFree (myAddrAttr);
      tmExit();
    }
    from = netConfigThread;
    if (tmMsgRecv (&from, NET_CONF_REPLY, &msg, INFINITY) != TM_MSGRECVOK)
    {
      printf ("NetAutoConfiguration: failed to get hwaddress (tmMsgRecv)!\n");
      vmFree (myAddrAttr);
      tmExit();
    }
    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: Received from netConfigThread \n");

    if (msg.msg.netConfReply.errno == NET_CONF_FAILED)
    {
      printf ("NetAutoConfiguration: No more devices left to configure, devices %i - %i have been configured\n",
              defaultDevice, (myDevice - 1) > 0 ? (myDevice - 1) : 0);
      moreDevToConfig = FALSE;
      continue;
      if (myDevice == defaultDevice)
      {
        printf ("NetAutoConfiguration: failed to get hwaddress for default device... exiting!\n");
        tmExit();
      }
    }
    else
    {
      for (i = 0; i < hwLen; i++)
      {
        switch (myAddrAttr[i].key)
        {
        case NETATTR_ETH_LOCAL_0:
          myHWAddress[0] = myAddrAttr[i].data>>8 & 0xFF;
          myHWAddress[1] = myAddrAttr[i].data & 0xFF;
          break;
        case NETATTR_ETH_LOCAL_1:
          myHWAddress[2] = myAddrAttr[i].data>>8 & 0xFF;
          myHWAddress[3] = myAddrAttr[i].data & 0xFF;
          break;
        case NETATTR_ETH_LOCAL_2:
          myHWAddress[4] = myAddrAttr[i].data>>8 & 0xFF;
          myHWAddress[5] = myAddrAttr[i].data & 0xFF;
          break;
        default:
          break;
        }
      }
    }

    netdbgPrintf (NETDEBUG_CONFIG, "NetAutoConfiguration: myHWAddress %x %x %x %x %x \n",
                  myHWAddress[0], myHWAddress[1], myHWAddress[2], myHWAddress[3], myHWAddress[4], myHWAddress[5]);
    nextState = STATE_ARP_FILL;

    // get my IP
    while (notQuit)
    {
      switch (nextState)
      {
      case STATE_ARP_FILL:

        netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration: entering STATE_ARP_FILL  \n");

        pa[0] = 16;    //length of ipv6-address
        pa[1] = 0xff;
        pa[2] = 0x02;
        pa[3] = 0x0;
        pa[4] = 0x0;
        pa[5] = 0x0;
        pa[6] = 0x0;
        pa[7] = 0x0;
        pa[8] = 0x0;
        pa[9] = 0x0;
        pa[10] = 0x0;
        pa[11] = 0x0;
        pa[12] = 0x1;
        pa[13] = 0xff;
        pa[14] = 0x0;
        pa[15] = 0x0;
        pa[16] = 0x4;

        ha[0] = 6;   //length of ethernet-address
        ha[1] = 0x33;
        ha[2] = 0x33;
        ha[3] = 0xff;
        ha[4] = 0x0;
        ha[5] = 0x0;
        ha[6] = 0x04;

        msg.msg.netARPAdd.proto = ARP_TYPE_IPv6;
        msg.msg.netARPAdd.device = myDevice;
        msg.id = NET_ARP_ADD;
        msg.msg.netARPAdd.pa = &pa[0];
        msg.msg.netARPAdd.ha = &ha[0];

        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: sending  NET_ARP_ADD\n");
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: netARPAdd.proto: %x\n", msg.msg.netARPAdd.proto);
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: netARPAdd.device %d\n", msg.msg.netARPAdd.device);
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: pa_length: %d \n", msg.msg.netARPAdd.pa[0]);
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: ha_length: %d \n", msg.msg.netARPAdd.ha[0]);
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: pa: %x%x.%x%x.%x%x.%x%x.%x%x.%x%x.%x%x.%x%x\n",
                     msg.msg.netARPAdd.pa[1], msg.msg.netARPAdd.pa[2], msg.msg.netARPAdd.pa[3], msg.msg.netARPAdd.pa[4],
                     msg.msg.netARPAdd.pa[5], msg.msg.netARPAdd.pa[6], msg.msg.netARPAdd.pa[7], msg.msg.netARPAdd.pa[8],
                     msg.msg.netARPAdd.pa[9], msg.msg.netARPAdd.pa[10], msg.msg.netARPAdd.pa[11], msg.msg.netARPAdd.pa[12],
                     msg.msg.netARPAdd.pa[13], msg.msg.netARPAdd.pa[14], msg.msg.netARPAdd.pa[15], msg.msg.netARPAdd.pa[16]);
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: ha: %x %x %x %x %x %x\n",
                     msg.msg.netARPAdd.ha[1], msg.msg.netARPAdd.ha[2], msg.msg.netARPAdd.ha[3],
                     msg.msg.netARPAdd.ha[4], msg.msg.netARPAdd.ha[5], msg.msg.netARPAdd.ha[6]);

        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: my threat ID: %d\n", msg.from);

        netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration : STATE_ARP_FILL: going to make arp-entry\n");

        /* send message to arp_main_thread */
        if ( tmMsgSend(arp_main_thread, &msg) != TM_MSGSENDOK )
        {
          printf("netAUTOCONFIG: tmMsgSend failed\n");
        }
        else
        {
          netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: failed to received arp_main_thread!\n");
        }

        nextState = STATE_CONFIG_IP6_ADRESS;
        netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration: STATE_ARP_FILL finished\n");

        break;

      case STATE_STARTED:

        netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration: STATE_STARTED\n");
        nextState = STATE_CONFIG_IP6_ADRESS;
        break;

      case STATE_CONFIG_IP6_ADRESS:

        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: entering STATE_CONFIG_IP6_ADRESS \n");


        Reply.yiaddr[0] = (LINK_LOCAL_ADDRESS_0 << 8) + LINK_LOCAL_ADDRESS_1;
        Reply.yiaddr[1] = 0;
        Reply.yiaddr[2] = 0;
        Reply.yiaddr[3] = 0;
        Reply.yiaddr[4] = (myHWAddress[0] << 8) + myHWAddress[1];
        Reply.yiaddr[5] = (myHWAddress[2] << 8) + 0xff;
        Reply.yiaddr[6] = 0xfe00 +  myHWAddress[3];
        Reply.yiaddr[7] = (myHWAddress[4] << 8) + myHWAddress[5] ;

        // set source IP to the one obtained by Local Link Combination
        msg.msg.netConf.AddrSet.deviceNr = myDevice;
        myAddrAttr[0].key = NETATTR_IP6_SOURCEADDRESS_0;
        myAddrAttr[1].key = NETATTR_IP6_SOURCEADDRESS_1;
        myAddrAttr[2].key = NETATTR_IP6_SOURCEADDRESS_2;
        myAddrAttr[3].key = NETATTR_IP6_SOURCEADDRESS_3;
        myAddrAttr[4].key = NETATTR_IP6_SOURCEADDRESS_4;
        myAddrAttr[5].key = NETATTR_IP6_SOURCEADDRESS_5;
        myAddrAttr[6].key = NETATTR_IP6_SOURCEADDRESS_6;
        myAddrAttr[7].key = NETATTR_IP6_SOURCEADDRESS_7;
        myAddrAttr[8].key = NETATTR_TYPE_IPv6;       // must know the type

        for (i = 0; i < 8; i++)
        {
          myAddrAttr[i].data = Reply.yiaddr[i];
        }
        myAddrAttr[8].data = 1;
        msg.id = NET_CONF_ADDRSET;
        msg.msg.netConf.AddrSet.attrVec = (Address) myAddrAttr;
        msg.msg.netConf.AddrSet.deviceNr = myDevice;
        msg.msg.netConf.AddrSet.len = 9;
        msg.msg.netConf.AddrSet.index = 0;

        if (tmMsgSend (netConfigThread, &msg) != TM_MSGSENDOK)
        {
          printf ("NetAutoConfiguration: failed to set set address (tmMsgSend)!\n");
          nextState = STATE_STARTED;
          break;
        }
        from = netConfigThread;
        if (tmMsgRecv (&from, NET_CONF_REPLY, &msg, INFINITY) != TM_MSGRECVOK)
        {
          printf ("NetAutoConfiguration: failed to set address (tmMsgRecv)!\n");
          nextState = STATE_STARTED;
          break;
        }

        if (msg.msg.netConfReply.errno == NET_CONF_FAILED)
        {
          printf ("NetAutoConfiguration: failed to unset address!\n");
          nextState = STATE_STARTED;
          break;
        }
        else
        {
          netdbgPrintf(0, "NetAutoConfiguration: set Address for device %i: \n                           %x:%x:%x:%x:%x:%x:%x:%x\n",
                       myDevice, Reply.yiaddr[0], Reply.yiaddr[1], Reply.yiaddr[2], Reply.yiaddr[3],
                       Reply.yiaddr[4], Reply.yiaddr[5], Reply.yiaddr[6], Reply.yiaddr[7] );
        }

        nextState = STATE_ARPLOOKUP;

        netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration: STATE_CONFIG_IP6_ADRESS finished\n");
        break;

      case STATE_ARPLOOKUP:
        // do ARP to check that this IP is not already used
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: entering STATE_FIRST_ARPLOOKUP\n");

        // ARP is done automatically here (after deleting the invalid entry)
        pa_len   = 16;
        proto    = ARP_TYPE_IPv6;
        device   = 0;

        arp_pa[0] = LINK_LOCAL_ADDRESS_0;
        arp_pa[1] = LINK_LOCAL_ADDRESS_1;
        arp_pa[2] = 0;
        arp_pa[3] = 0;
        arp_pa[4] = 0;
        arp_pa[5] = 0;
        arp_pa[6] = 0;
        arp_pa[7] = 0;
        arp_pa[8] = myHWAddress[0];
        arp_pa[9] = myHWAddress[1];
        arp_pa[10] = myHWAddress[2];
        arp_pa[11] = 0xff;
        arp_pa[12] = 0xfe;
        arp_pa[13] = myHWAddress[3];
        arp_pa[14] = myHWAddress[4];
        arp_pa[15] = myHWAddress[5];

        msg.id = NET_ARP_REQ;
        msg.msg.netARPReq.proto = proto;
        msg.msg.netARPReq.device = myDevice;
        msg.msg.netARPReq.pa = arp_pa;
        msg.msg.netARPReq.pa_len = pa_len;

        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: Sending to arp_main_thread\n");
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: Device = %x\n", myDevice);

        netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration: STATE_FIRST_ARPLOOKUP: going to make arp-entry\n");
        if (tmMsgSend (arp_main_thread, &msg) != TM_MSGSENDOK )
        {
          printf ("NetAutoConfiguration: failed to send ARP-Request!\n");
          nextState = STATE_STARTED;
          break;
        }

        from = arp_main_thread;
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: Waiting for answer from ARP-main....\n");

        if (tmMsgRecv (&from, ANYMSGTYPE, &reply, INFINITY) != TM_MSGRECVOK )
        {
          printf ("NetAutoConfiguration: failed to receive ARP-Reply (Request 1)!\n");
          nextState = STATE_STARTED;
          break;
        }
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "AutoConfiguration: Receiving form  arp_main_thread!\n");

        if ( reply.msg.netARPReply.status != ARP_NOTFOUND )
        {
          printf ("NetAutoConfiguration: address already in use, Autoconfiguration failed for this device!\n");
          //(jb) now the tentative address in the device should be unset, but the interface to netConfigThread
          //does not mplement that... so we are setting the address to the unspecified address (::)
          for (i = 0; i < 8; i++)
          {
            myAddrAttr[i].data = 0;
          }
          myAddrAttr[8].data = 1;
          msg.id = NET_CONF_ADDRSET;
          msg.msg.netConf.AddrSet.attrVec = (Address) myAddrAttr;
          msg.msg.netConf.AddrSet.deviceNr = myDevice;
          msg.msg.netConf.AddrSet.len = 9;
          msg.msg.netConf.AddrSet.index = 0;

          if (tmMsgSend (netConfigThread, &msg) != TM_MSGSENDOK)
          {
            printf ("NetAutoConfiguration: failed to unset address (tmMsgSend)!\n");
            nextState = STATE_STARTED;
            break;
          }
          from = netConfigThread;
          if (tmMsgRecv (&from, NET_CONF_REPLY, &msg, INFINITY) != TM_MSGRECVOK)
          {
            printf ("NetAutoConfiguration: failed to unset address (tmMsgRecv)!\n");
            nextState = STATE_STARTED;
            break;
          }

          if (msg.msg.netConfReply.errno == NET_CONF_FAILED)
          {
            printf ("NetAutoConfiguration: failed to unset address!\n");
            nextState = STATE_STARTED;
            break;
          }
          else
          {
            netdbgPrintf(0, "NetAutoConfiguration: reset device to unspecified address!\n" );
          }

          nextState = STATE_STARTED;
          break;
        }
        if ( reply.msg.netARPReply.status == ARP_NOTFOUND )
        {
          printf ("NetAutoConfiguration: address not in use!\n");
        }

        nextState = STATE_DUBLICATE_DETECTION_COMPLETE;

        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: STATE_FIRST_ARPLOOKUP finished\n");
        break;

      case STATE_DUBLICATE_DETECTION_COMPLETE:
        netdbgPrintf (NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: entering STATE_VERIFY_COMPLETE\n");

        deviceNr = myDevice;
        if (! netdevGet(deviceNr, &d) )
        {
          printf ("NetAutoConfiguration: failed to set address!\n");
          nextState = STATE_DUBLICATE_DETECTION_COMPLETE;
        }

        /*  				    if (!( netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_0, &val[0]) && */
        /*  					   netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_1, &val[1]) && */
        /*  					   netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_2, &val[2]) && */
        /*  					   netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_3, &val[3]) && */
        /*  					   netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_4, &val[4]) && */
        /*  					   netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_5, &val[5]) && */
        /*  					   netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_6, &val[6]) && */
        /*  					   netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_7, &val[7]) )) { */
        /*                                          //failed what now: Normaly we would dump the packet */
        /*                                          //How can it be that we do not know our IF_ADDR this will be */
        /*                                          //set when the device is allocated  */
        /*  				        printf ("NetAutoConfiguration: no ethernet device found \n");  */
        /*  					nextState = STATE_DUBLICATE_DETECTION_COMPLETE; */
        /*  					break; */
        /*  				    } */

        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: Verify Adress for device %x\n", deviceNr); */
        /*  				    printf("NetAutoConfiguration:  Adress for device set: %x:%x:%x:%x:%x:%x:%x:%x\n", */
        /*  						 val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]); */
        /*  				    printf("------------------------------------------------------------------------------\n"); */
        /*  				    printf ("NetAutoConfiguration: Configuration for device %i complete!\n", deviceNr); */

        //				    nextState =  STATE_UDP_TEST;
        nextState = STATE_FINISH;

        netdbgPrintf (NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: STATE_VERIFY_COMPLETE done\n");
        break;

        /*  			     case STATE_ARP_ADD_MYIPv6: */

        /*  		 	            //going to insert host from which this solicitation came into arp-daemon */
        /*  			            netdbgPrintf (NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: entering STATE_ARP_ADD_MYIPv6\n"); */

        /*  				    deviceNr = myDevice; */
        /*  				    if (! netdevGet(deviceNr, &d) ) { */
        /*  				         printf ("NetAutoConfiguration: failed to set address!\n"); */
        /*  					 nextState = STATE_ARP_ADD_MYIPv6; */
        /*  				    } */
        /*  				    netdbgPrintf (NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: entering STATE_ARP_ADD_MYIPv6\n"); */
        /*  				    if (!(  netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_0, &val[0]) && */
        /*  					    netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_1, &val[1]) && */
        /*  					    netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_2, &val[2]) && */
        /*  					    netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_3, &val[3]) && */
        /*  					    netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_4, &val[4]) && */
        /*  					    netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_5, &val[5]) && */
        /*  				 	    netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_6, &val[6]) && */
        /*  					    netattrGet(d->addrList->addr,  NETATTR_IP6_SOURCEADDRESS_7, &val[7]) )) { */
        /*  				         // failed what now: Normaly we would dump the packet */
        /*  					 //How can it be that we do not know our IF_ADDR this will be */
        /*  					 // set when the device is allocated  */
        /*  				         printf ("NETDEBUG_AUTOCONFIG: no ethernet device found \n");  */
        /*  					 nextState = STATE_ARP_ADD_MYIPv6; */
        /*  					 break; */
        /*  				    } */

        /*  				    pa[0] = 16;    //length of ipv6-address  */
        /*  				    pa[1]  = val[0] >> 8;   pa[2]  = val[0] & 0xff;   pa[3]  = val[1] >> 8 ;  pa[4]  = val[1] & 0xff;  */
        /*  				    pa[5]  = val[2] >> 8;   pa[6]  = val[2] & 0xff;   pa[7]  = val[3] >> 8;   pa[8]  = val[3] & 0xff;   */
        /*  				    pa[9]  = val[4] >> 8;   pa[10] = val[4] & 0xff;   pa[11] = val[5] >> 8;   pa[12] = val[5] & 0xff;    */
        /*  				    pa[13] = val[6] >> 8;   pa[14] = val[6] & 0xff;   pa[15] = val[7] >> 8 ;  pa[16] = val[7] & 0xff ; */

        /*  				    ha[0] = 6;   //length of ethernet-address */
        /*  				    ha[1] = myHWAddress[0];   ha[2] = myHWAddress[1];   ha[3] = myHWAddress[2];   */
        /*  				    ha[4] = myHWAddress[3];   ha[5] = myHWAddress[4];   ha[6] = myHWAddress[5]; */

        /*  				    msg.msg.netARPAdd.proto = ARP_TYPE_IPv6; */
        /*  				    msg.msg.netARPAdd.device = myDevice; */
        /*  				    msg.id = NET_ARP_ADD; */
        /*  				    msg.msg.netARPAdd.pa = &pa[0]; */
        /*  				    msg.msg.netARPAdd.ha = &ha[0];   */

        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration :  STATE_ARP_ADD_MYIPv6: going to make arp-entry\n"); */
        /*  				    // send message to arp_main_thread  */
        /*  				    if ( tmMsgSend(arp_main_thread, &msg) != TM_MSGSENDOK ) { */
        /*                    			  netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: tmMsgSend failed\n"); */
        /*  					  nextState = STATE_STARTED; */
        /*  					  // nextState = STATE_FINISH; */
        /*  					  break; */
        /*  				    } */

        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: sending  NET_ARP_ADD\n"); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: netARPAdd.proto: %x\n", msg.msg.netARPAdd.proto); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: netARPAdd.device %d\n", msg.msg.netARPAdd.device); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: pa_length: %d \n", msg.msg.netARPAdd.pa[0]); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: ha-length: %d \n", msg.msg.netARPAdd.ha[0]); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: pa[0]: %x\n", msg.msg.netARPAdd.pa[1]); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: pa[1]: %x\n", msg.msg.netARPAdd.pa[2]); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: ha[0]: %x\n", msg.msg.netARPAdd.ha[1]); */
        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: ha[1]: %x\n", msg.msg.netARPAdd.ha[2]); */

        /*  				    nextState = STATE_FINISH;   */

        /*  				    netdbgPrintf(NETDEBUG_AUTOCONFIG,  "NetAutoConfiguration: STATE_ARP_ADD_MYIPv6 done\n"); */
        /*  				    break; */

      case STATE_FINISH:
        netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: STATE FINISH\n");
        configuredDefaultDevice = TRUE;
        notQuit = FALSE;
        break;

      default:
        printf ("NetAutoConfiguration: PANIC, unknown STATE entered... resetting!\n");
        nextState = STATE_STARTED;
        break;
      }

    }
    myDevice++;
    netdbgPrintf(NETDEBUG_AUTOCONFIG, "NetAutoConfiguration: changing for device %d\n", myDevice);
  }

  /*
    printf("TMUDPSEND: starting to send to NetAppli arg=%d\n",arg);
         //msg.from = netAutoConfiguration; 
  msg.id = TM_UDP_SEND;
  msg.msg.tmUDPSend.buffer = buffer;
  msg.msg.tmUDPSend.len = blen;
  printf("id     %x\n", msg.id);
  printf("buffer %x %x\n", buffer, msg.msg.tmUDPSend.buffer); 
  printf(" blen  %x %x\n", blen,  msg.msg.tmUDPSend.len);

  printf("TMUDPSEND: starting to send to NetAppli\n");

  if ( tmMsgSend(net_appli_thread, &msg) != TM_MSGSENDOK ){ 
         printf("TMUDPSEND: Receive failed (tmMsgSend)\n");
}
  */



  vmFree(myAddrAttr);
  printf("NetAutoConfiguration: finished!\n");

  tmExit();		// do not remove this unless you know what you are doing

}
