/* 
 * sim_util.c
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1996,1993,1991,1990  Arizona Board of Regents
 */

#include <sys/types.h>
#include "x_stdio.h"
#include "xkernel.h"
#include "eth.h"
#include "eth_i.h"
#include "ip.h"
#include "ip_i.h"
#include "sim_i.h"

#define MAX_MAP_HOSTS 500
static Key *HostMap[MAX_MAP_HOSTS];
static int HostMapNum=0;

char
*xMallocZero(int size)
{
  char *cp;

  cp = xMalloc(size);
  bzero(cp, size);
  return cp;
}

char
*sim_getTime()
{
  long   sec, usec;
  XTime t;
  static char buf[100];

  xGetTime(&t);
  sec  = t.sec - sim_begTime.sec;
  usec = t.usec - sim_begTime.usec;
  if (usec < 0) {
    sec -= 1;
    usec += 1000000;
  }
  sprintf(buf, "%03ld.%06ld", sec, usec);
  return buf;
}

char
*sim_addr2str (void *h, int type)
{
  char		*s;
  ETHhost	*eh;
  IPhost	*ih;
  static char 	str[200], *cp=str;

  if (cp-str > 170)
    cp = str;
  if (type == TYPE_ETH) {
    eh = (ETHhost *) h;
    sprintf(cp, "%d.%d.%d.%d.%d.%d", (eh->high)>>8, (eh->high)&0xff,
	    (eh->mid)>>8, (eh->mid)&0xff, (eh->low)>>8, (eh->low)&0xff);
  }
  else if (type == TYPE_IP) {
    ih = (IPhost *) h;
    sprintf(cp, "%d.%d.%d.%d", (int)ih->a, (int)ih->b, (int)ih->c,
	    (int)ih->d);
  }
  else 
    strcpy(cp, "wrong type");
  cp = (s = cp) + strlen(cp) + 1;

  return s;
}

char
*sim_simaddr2str (Simhost *h)
{
  char		*s;
  ETHhost	*eh;
  IPhost	*ih;
  static char 	str[200], *cp=str;

  if (cp-str > 170)
    cp = str;
  if (h->type == TYPE_ETH) {
    eh = &h->addr.eth;
    sprintf(cp, "%d.%d.%d.%d.%d.%d", (eh->high)>>8, (eh->high)&0xff,
	    (eh->mid)>>8, (eh->mid)&0xff, (eh->low)>>8, (eh->low)&0xff);
  }
  else if (h->type == TYPE_IP) {
    ih = &h->addr.ip;
    sprintf(cp, "%d.%d.%d.%d", (int)ih->a, (int)ih->b, (int)ih->c,
	    (int)ih->d);
  }
  else 
    strcpy(cp, "wrong type");
  cp = (s = cp) + strlen(cp) + 1;

  return s;
}

void
sim_print_packet (SimPacket *pkt)
{
  printf("                 [packet] src: %s, hop: %s, \n",
	 sim_simaddr2str(&(pkt->src)), sim_simaddr2str(&(pkt->hop)));
    printf("                          dst: %s, len: %d\n", 
	   sim_simaddr2str(&(pkt->dst)), pkt->len);
}

Key 
*sim_obj2key (SIM_PSTATE *ps, char *obj)
{
  int k;
  Key *kp=NULL;
  
  for (k=0; k<ps->numHosts; k++)
    if (obj == ps->keyMap[k].obj) {
      kp = &(ps->keyMap[k]);
      break;
    }
  xsimDbg(SL0_FLAG,
	  printf("               obj2key returning &(ps->keyMap[%d])\n", k));
  return kp;
}

Key 
*sim_addr2key (SIM_PSTATE *ps, char *addr, int type)
{
  int 		k;
  ETHhost	*ethAddr=((ETHhost *)addr);
  IPhost	*ipAddr=((IPhost *)addr);
  Key		*kp;
  

  if (type == TYPE_ETH) {
    if ( mapResolve(ps->ethAddr2Key, ethAddr, (void **)&kp) != XK_SUCCESS )
      kp = NULL;
/*
    for (k=0; k<ps->numHosts; k++) 
      if (!bcmp((char *)ethAddr, (char *)&( ps->keyMap[k].ethAddr), 
		sizeof(ETHhost))) {
	kp = &(ps->keyMap[k]);
	break;
      }
*/
  }
  else if (type == TYPE_IP) {
    if ( mapResolve(ps->ipAddr2Key, ipAddr, (void **)&kp) != XK_SUCCESS )
      kp = NULL;
/*
    for (k=0; k<ps->numHosts; k++) 
      if (!bcmp((char *)ipAddr, (char *)&(ps->keyMap[k].ipAddr), 
		sizeof(IPhost))) {
	kp = &(ps->keyMap[k]);
	break;
      }
*/
  }
  xsimDbg(SL0_FLAG,
	  printf("               addr2key, type:%d rv: &(ps->keyMap[%d])\n", 
		 type, k));
  return kp;
}

Key 
*sim_name2key (SIM_PSTATE *ps, char *name)
{
  int k;
  Key *kp=NULL;
  
  for (k=0; k<ps->numHosts; k++)
    if (!strcmp(ps->keyMap[k].name, name)) {
      kp = &(ps->keyMap[k]);
      break;
    }
  xsimDbg(SL0_FLAG,
	  printf("    name2key for %s returning &(ps->keyMap[%d])\n", 
		 name, k));
  return kp;
}

void 
xsimAddHostMap(Key *kp)
{
  HostMap[HostMapNum++] = kp;
  if (HostMapNum > MAX_MAP_HOSTS)
    Kabort("ERROR: Need to increase MAX_MAP_HOSTS\n");
}

int
xsimGetIPaddr(char *fullName, IPhost *host)
{
  int		k;
  Key		*kp;

  for (k=0; k<HostMapNum; k++)
    if (!strcmp(HostMap[k]->name, fullName)) {
      kp = HostMap[k];
      *host = kp->ipAddr;
      return 0;
    }
  host->a = host->b = host->c = host->d = 0;
  return 1;
}
  
int
xsimGetETHaddr(char *fullName, ETHhost *host)
{
  int		k;
  Key		*kp;

  for (k=0; k<HostMapNum; k++)
    if (!strcmp(HostMap[k]->name, fullName)) {
      kp = HostMap[k];
      *host = kp->ethAddr;
      return 0;
    }
  host->high = host->mid = host->low = 0;
  return 1;
}
