/************************************************************************/
/*	Routing Protocol Simulator	Release 1.0	1994/3/17	*/
/*                                              1.21    1997/2/10       */
/*									*/
/*		module 	: common routine           		        */
/*		file	: syslib.c			       		*/
/*									*/
/*   Copyright (c) 1994-1997 by Systems Development Laboratory Hitachi,	*/
/*   Ltd. All rights reserved.						*/
/*----------------------------------------------------------------------*/
/*	UPDATE HISTORY							*/
/*									*/
/************************************************************************/
static char copyright[]=
  "@(#)Copyright (c) 1994-1997 by Systems Development Laboratory Hitachi,Ltd.\n All rights researved.\n";

#ifdef VXWORKS

#include "stdioLib.h"
#include "hostLib.h"
#include "in.h"
#include "socket.h"
#include "net/if.h"
#include "net/if_ether.h"
#include "memLib.h"
#include "intLib.h"
#include "semLib.h"

#define SECOND	sysClkRateGet()
#define MINUTE  60
#define HOUR	60

PART_ID mem_part = NULL;
SEM_ID lock_sem;

#else  /* VXWORKS */

#include "rps.h"
#include <sys/socket.h>
#ifdef LINUX
#include <sys/socketio.h>
#else
#include <sys/sockio.h>
#endif /* LINUX */
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/file.h>
#ifndef BSD
#ifndef LINUX
#include <sys/stropts.h>
#endif /* LINUX */
#ifdef USE_ICMP
#include <net/nit_if.h>
#include <net/nit_buf.h>
#include <net/nit_buf.h>
#endif /* USE_ICMP */
#endif /* BSD */
#include <net/route.h>
#include <net/if.h>
#include <netinet/in.h>
#ifdef USE_ICMP
#include <netinet/if_ether.h>
#endif /* USE_ICMP */
#include <signal.h>

char *ctime();
struct hostent *gethostbyaddr();

#define IFCONF_BUF_SIZE 	5000

int ether_fd;
fd_set read_fd;
int max_fd;

#endif  /* VXWORKS */

extern char *get_ip_buff();

int recv_flag = 0;
unsigned int recv_intf;
unsigned int rintf;
#ifdef USE_ICMP
char ether_frame_buff[1500];
int recv_ether_frame();
#endif /* USE_ICMP */
char *inetaddr_to_char();
struct ifreq if_info;
char *ip_buff;

/*

  mem_alloc

*/
char *mem_alloc(size)
int size;
{
#ifdef VXWORKS
    char *mp;

    if(!mem_part) {
	mp = malloc(size);
	mem_part = memPartCreate(mp,size);
	return mp;
    }
    else {
	mp = (char *)memPartAlloc(mem_part,size);
    }

    return mp;

#else  /* VXWORKS */

    return (char *)malloc(size);

#endif /* VXWORKS */
    
}

/*

  mem_free

*/
void mem_free(buf)
char *buf;
{
#ifdef VXWORKS

    memPartFree(mem_part,buf);

#else

    free(buf);

#endif

}
    
/*

  time_to_char

*/
char *time_to_char(clock)
int *clock;
{
#ifdef VXWORKS
    static char t_str[16];
    int sec,min,hour;

    bzero(t_str,sizeof(t_str));
    
/*    printf("clock = %d\n",*clock);*/
    sec = *clock / SECOND;
    min = sec / MINUTE;
    hour = min / HOUR;
    
    t_str[0] = ' ';
    t_str[1] = ' ';
    t_str[2] = ' ';
    t_str[3] = ' ';    
    t_str[4] = hour / 10 + '0';
    t_str[5] = hour % 10 + '0';
    t_str[6] = ':';
    min -= hour * HOUR;
    t_str[7] = min / 10 + '0';
    t_str[8] = min % 10 + '0';
    t_str[9] = ':';
    sec -= min * MINUTE;
    t_str[10] = sec / 10 + '0';
    t_str[11] = sec % 10 + '0';
    t_str[12] = '\0';
    
    return t_str ;

#else

    return(ctime((time_t *)clock));
#endif
}

int asc_to_int(string)
char *string;
{
#ifdef VXWORKS
    char c;
    char *tmp;
    int num;

    num = 0;
    tmp = string;
    while(*tmp) {
	c = *tmp++;
	num = num*10 + c - '0';
    }
    
    return num;

#else

    return atoi(string);

#endif
}

int asc_to_long(string)
char *string;
{
#ifdef VXWORKS
    char c;
    char *tmp;
    long num;

    num = 0;
    tmp = string;
    while(*tmp) {
	c = *tmp++;
	num = num*10 + c - '0';
    }
    
    return num;

#else

    return atol(string);

#endif
}

/*

  time_conv

*/
int time_conv(t)
time_t t;
{
#ifdef VXWORKS

    return (t / sysClkRateGet());

#else

    return t;
    
#endif
    
}

/*

  sys_route_add

*/
void sys_route_add(dst,gw)
u_long dst;
u_long gw;
{

#ifdef VXWORKS
    char dst_addr[16],gw_addr[16];

    strcpy(dst_addr,inetaddr_to_char(dst));
    strcpy(gw_addr,inetaddr_to_char(gw));
    
    routeAdd(dst_addr,gw_addr);

#else  /* VXWORKS */

#ifndef BSD

    struct rtentry route;
    int s;
    struct sockaddr_in *dst_addr,*gw_addr;

    if((s = socket(PF_INET,SOCK_DGRAM,0)) < 0) {
	perror("socket");
	exit(0);
    }
       
    dst_addr = (struct sockaddr_in *)&route.rt_dst;
    gw_addr = (struct sockaddr_in *)&route.rt_gateway;
       
    bzero(&route,sizeof(struct rtentry));
    bzero(dst_addr,sizeof(struct sockaddr_in));
    bzero(gw_addr,sizeof(struct sockaddr_in));

    dst_addr->sin_family = AF_INET;
    dst_addr->sin_addr.s_addr = dst;

    gw_addr->sin_family = AF_INET;
    gw_addr->sin_addr.s_addr = gw;

    if(gw == 0x7f000001) {
	route.rt_flags = RTF_HOST;
    }
    else {
	route.rt_flags = RTF_GATEWAY;
    }
    if(ioctl(s,SIOCADDRT,(char *)&route))
      perror("ioctl<SIOCADDRT>");

    close(s);

#endif /* BSD */
 
#endif /* VXWORKS */

}

/*

  sys_route_delete

*/
void sys_route_delete(dst,gw)
u_long dst;
u_long gw;
{

#ifdef VXWORKS
    char dst_addr[16],gw_addr[16];

    strcpy(dst_addr,inetaddr_to_char(dst));
    strcpy(gw_addr,inetaddr_to_char(gw));
    
    routeDelete(dst_addr,gw_addr);

#else

#ifndef BSD

    struct rtentry route;
    int s;
    struct sockaddr_in *dst_addr,*gw_addr;

    if((s = socket(PF_INET,SOCK_DGRAM,0)) < 0) {
	perror("socket");
	exit(0);
    }
       
    dst_addr = (struct sockaddr_in *)&route.rt_dst;
    gw_addr = (struct sockaddr_in *)&route.rt_gateway;
       
    bzero(&route,sizeof(struct rtentry));
    bzero(dst_addr,sizeof(struct sockaddr_in));
    bzero(gw_addr,sizeof(struct sockaddr_in));

    dst_addr->sin_family = AF_INET;
    dst_addr->sin_addr.s_addr = dst;

    gw_addr->sin_family = AF_INET;
    gw_addr->sin_addr.s_addr = gw;

    if(gw == 0x7f000001) {
	route.rt_flags = RTF_HOST;
    }
    else {
	route.rt_flags = RTF_GATEWAY;
    }
    if(ioctl(s,SIOCDELRT,(char *)&route))
      perror("ioctl<SIOCDELRT>");

    close(s);

#endif  /* BSD */
  
#endif  /* VXWORKS */
}

#ifdef USE_ICMP
/*

  ether_init

*/
int ether_init(intf)
u_long intf;
{
    
#ifdef VXWORKS

    etherInputHookAdd(recv_ether_frame);

#else

    int s;
    struct ifconf ifconf_req;
    char *ifcp;
    int len;
    struct sockaddr_in *if_addr;
    struct ifreq *ifrp;

    printf("ether_init\n");
    
    FD_ZERO(&read_fd);
    
    if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1) {
	perror("socket");
	return -1;
    }

    if((ifcp = (char *)malloc(IFCONF_BUF_SIZE)) == NULL) {
	perror("malloc");
	return -1;
    }
    
    ifconf_req.ifc_buf = ifcp;
    ifconf_req.ifc_len = IFCONF_BUF_SIZE;
    
    if(ioctl(s,SIOCGIFCONF,(char *)&ifconf_req)<0) {
	perror("SIOCGIFCONF");
	return -1;
    }

    len = ifconf_req.ifc_len;
    for(ifrp=ifconf_req.ifc_req,len=0;len<ifconf_req.ifc_len;ifrp++,len+=sizeof(struct ifreq)) {
	if_addr = (struct sockaddr_in *)&ifrp->ifr_addr;
	if(intf == (u_long)if_addr->sin_addr.s_addr) 
	   break; 
    }
    
    bcopy(ifrp,&if_info,sizeof(struct ifreq));
    
    free(ifcp);

#endif

    ip_buff = get_ip_buff();
}

#ifdef VXWORKS

BOOL recv_ether_frame(ifp,buff,len)
struct ifnet *ifp;
char *buff;
int len;
{
    unsigned int if_addr;
    struct in_addr addr;
    char *packet;
    struct ether_header *eh;
    u_char *tmp;
    
    if(!recv_flag) return FALSE;

    eh = (struct ether_header *)buff;
    addr = ((struct sockaddr_in *)ifp->if_addrlist)->sin_addr;
    if_addr = recv_intf = addr.s_addr;

/*    printf("if_addr = %s len = %d\n",inetaddr_to_char(if_addr),len);
    tmp = eh->ether_dhost;
    printf("%x.%x.%x.%x.%x.%x\n",*tmp,*(tmp+1),*(tmp+2),*(tmp+3),*(tmp+4),*(tmp+5));

    tmp = eh->ether_shost;
    printf("%x.%x.%x.%x.%x.%x\n",*tmp,*(tmp+1),*(tmp+2),*(tmp+3),*(tmp+4),*(tmp+5));
    printf("ethertype = %x\n",eh->ether_type);
*/    
    packet = buff + sizeof(struct ether_header);

    if(ip_protocol_check(packet)) {
	recv_frame_copy(NULL,0,if_addr);
	bcopy(packet,ip_buff,len-sizeof(struct ether_header));
	return TRUE;
    }
    
    return FALSE;
}

#else

int ether_read()
/*
byte *buf;
int buf_len;
*/
{
    int len;
    struct ether_header *eh;
    fd_set fd;
    struct timeval t;

    t.tv_sec = 0;
    t.tv_usec = 0;

    fd = read_fd;
    select(max_fd+1,&fd,NULL,NULL,&t);

    if(FD_ISSET(ether_fd,&fd)) {
	if((len = read(ether_fd,ether_frame_buff,1500)) > 0) {
	    bcopy(ether_frame_buff+sizeof(struct ether_header),ip_buff,len);
	    recv_intf = rintf;
	    return len;
	}
	return -1;
    }

    return -1;
}

#endif

/*

  frame_recv_init

*/
void frame_recv_init(intf)
unsigned long intf;
{
    
#ifdef VXWORKS
/*    recv_intf = intf;*/
    recv_flag = 1;
    
#else  /* VXWORKS */

#ifndef BSD

    struct strioctl si;
    struct ifreq ifr;
    
    if((ether_fd = open("/dev/nit",O_RDONLY)) == -1) {
	perror("nit open");
	return ;
    }

    if(ioctl(ether_fd,I_SRDOPT,(char *)RMSGD)) {
	perror("I_SRDOPT");
	return ;
    }

    strncpy(ifr.ifr_name,if_info.ifr_name,sizeof(ifr.ifr_name));
    ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
    si.ic_cmd = NIOCBIND;
    si.ic_timout = 0;
    si.ic_len = sizeof(ifr);
    si.ic_dp = (char *)&ifr;

    if(ioctl(ether_fd,I_STR,(char *)&si)) {
	perror("I_STR");
	return ;
    }

    FD_SET(ether_fd,&read_fd);
    max_fd = ether_fd;
    recv_frame_copy(NULL,0,ether_fd);
    rintf = intf;

#endif  /* BSD */

#endif  /* VXWORKS */

}


/*

  frame_recv_term

*/
void frame_recv_term()
{
#ifdef VXWORKS
    
    recv_flag = 0;
    frame_buff_clear();
    etherInputHookAdd(NULL);
    
#else

    close(ether_fd);

#endif
    
}

/*

  get_frame_recv_intf

*/
u_long get_frame_recv_intf()
{
    return recv_intf;
}

#endif /* USE_ICMP */

/*

  sem_init

*/
void sem_init()
{

#ifdef VXWORKS

/*    lock_sem = semBCreate(SEM_Q_PRIORITY,SEM_FULL);*/

#else

#endif
}

/*

  int_lock

*/
int int_lock()
{

#ifdef VXWORKS

    return intLock();
/*    semTake(lock_sem,WAIT_FOREVER);*/
    return 0;

#else

    /*    return sigblock(SIGALRM);*/
/*    return 0;*/

#endif

}

/*

  int_unlock

*/
void int_unlock(lock)
int lock;
{

#ifdef VXWORKS
    
/*    semGive(lock_sem);*/
    intUnlock(lock);

#else

    /*    sigsetmask(SIGALRM); */
    
#endif

}







