/******************************************************************************
版权所有：	
文件名称：	rt_socket.c
文件版本：	01.01
创建作者：	sunxi
创建日期：	2020-06-18
功能说明：	实时微系统网络接口.所有接口必须在线程中调用，不能在中断中调用。
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include <rt.h>

#include "rt_socket.h"
#include "rt_printf.h"
#include <linux/route.h>

#include "bspconfig.h"

/*------------------------------- 宏定义 --------------------------------------
*/


/*------------------------------ 类型结构 -------------------------------------
*/


/*------------------------------ 全局变量 -------------------------------------
*/
char * g_if_name[] = 
{
	"eth0",
	"eth1",
	"eth2", 
	"eth3",
	"eth4",
};




#define IF_NUM ((int)(sizeof(g_if_name)/4))

int g_net_num = CFG_ETH_MAX_PHY; // 正常的网口数量


/*------------------------------ 函数声明 -------------------------------------
*/
  

/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/
int rt_socket_init(void)
{
	unsigned int ret;
	// 目前工厂主板标准硬件版本为0，2个网口。
	// 以后如果使用3个网口，需修改硬件版本号。
	ret = 3;// gpio_get_version();
	if(ret < 3)
	{
		g_net_num = 2;
	}

	return 0;
}
 

// 打开关闭
SOCKET rt_socket (int domain, int type, int protocol)
{
	SOCKET s;

	s = socket(domain, type, protocol);

	return s;
}


int rt_socket_close (SOCKET s)
{

	if(s > 0)
	{ 
		close(s);
 	}
	
	return 0;
}


//连接
SOCKET rt_accept (SOCKET s, struct sockaddr * addr, unsigned int * addr_len)
{
	SOCKET newsock = 0;

	newsock = accept(s, addr, addr_len);

	return newsock;
}


int rt_bind (SOCKET s, struct sockaddr * addr, unsigned int len)
{
	return bind(s, addr, len);
}


int rt_connect (SOCKET s, struct sockaddr * addr, unsigned int len)
{
	return connect(s, addr, len);
}


int rt_listen (SOCKET s, int n)
{
	return listen(s, n);
}


int rt_shutdown (SOCKET s, int how)
{
	return shutdown(s, how);
}


//接收发送
int rt_send(SOCKET s, void *buf, int n, int flags)
{
	// flags加上MSG_NOSIGNAL标志，解决主循环在此断开的socket上继续发送数据，引起系统异常的问题。
	// return rt_sendto(s,buf,n,flags,NULL,0);
	return sendto(s, buf, n, flags | MSG_NOSIGNAL, NULL, 0);
}


int rt_recv (SOCKET s, void *buf, int n, int flags)
{
	return rt_recvfrom(s, buf, n, flags, NULL, 0);
}


int rt_sendto (SOCKET s,  void *buf, int n,int flags,  struct sockaddr * addr, unsigned int addr_len)
{
	return sendto(s, buf, n, flags, addr, addr_len);
}


int rt_recvfrom (SOCKET s, void * buf, int n, int flags, struct sockaddr * addr, unsigned int * addr_len)
{
	return recvfrom(s, buf, n, flags, addr, addr_len);
}
 

//控制
int rt_getsockname (SOCKET s, struct sockaddr * addr,	unsigned int * len)
{
	return getsockname(s, addr, len);
}


int rt_getpeername (SOCKET s, struct sockaddr * addr,unsigned int * len)
{
	return getpeername(s, addr, len);
}


int rt_getsockopt (SOCKET s, int level, int optname,void * optval,unsigned int * optlen)
{
	return getsockopt(s, level, optname, optval, optlen);
}


int rt_setsockopt (SOCKET s, int level, int optname,  void *optval, unsigned int optlen)
{
	return setsockopt(s, level, optname, optval, optlen);
}


int rt_sockioctl(SOCKET s, int cmd, uint32_t arg)
{
	return ioctl(s, cmd, arg);
}

int set_net_param_fun(char* NetNum,char* para,char* cmd)
{
  	int ret;

	char argv[256] = {0x00};

	//sprintf(argv, "/bin/ifconfig %s %s %s", NetNum,para,cmd);

	sprintf(argv, "ifconfig %s %s %d.%d.%d.%d", NetNum,para,cmd[0],cmd[1],cmd[2],cmd[3]);

#ifdef RT_SOCKET_DEBUG
	rt_printf("sh cmd=%s\r\n",argv);
#endif

	ret = system(argv);

	return ret;
}

int set_gw_param_fun(char* ip,char* gw)
{
  	int ret;

	char argv[256] = {0x00};

	//sprintf(argv, "/bin/ifconfig %s %s %s", NetNum,para,cmd);

	sprintf(argv, "route add %s gw %s",ip,gw);

#ifdef RT_SOCKET_DEBUG
	rt_printf("sh cmd=%s\r\n",argv);
#endif
	ret = system(argv);

	return ret;
}

#if 0 // 没有用到
int rt_sockconnected(SOCKET s) 
{ 
	struct tcp_info info; 
	int len=sizeof(info);	
	int ret=-1;
	
	if(!s) 
		return ret; 
 
 	memset(&info, 0, sizeof(info));
	ret=rt_getsockopt(s, IPPROTO_TCP, TCP_INFO, (char *)&info, &len); 
	if(info.tcpi_state==1) 
	{ 
		//处于链接状态
		ret = 0; 
	} 
	else 
	{ 
		//处于断开状态
		ret = -1;  
	} 
	
	return ret;
}

int rt_net_set_KeepAlive(SOCKET s, int interval)  
{  
    int val = interval;  
    //开启keepalive机制  
    if (rt_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1)  
    {  
//        printf("setsockopt SO_KEEPALIVE: %s", strerror(errno));  
        return -1;  
    }  
  

    /* Default settings are more or less garbage, with the keepalive time 
     * set to 7200 by default on Linux. Modify settings to make the feature 
     * actually useful. */  
  
    /* Send first probe after interval. */  
    val = interval;  
    if (rt_setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {  
  //      printf("setsockopt TCP_KEEPIDLE: %s\n", strerror(errno));  
        return -1;  
    }  
  
    /* Send next probes after the specified interval. Note that we set the 
     * delay as interval / 3, as we send three probes before detecting 
     * an error (see the next setsockopt call). */  
    val = interval / 3;  
    if (val == 0) val = 1;  
    if (rt_setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {  
 //       printf("setsockopt TCP_KEEPINTVL: %s\n", strerror(errno));  
        return -1;  
    }  
  
    /* Consider the socket in error state after three we send three ACK 
     * probes without getting a reply. */  
    val = 3;  
    if (rt_setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {  
 //       printf("setsockopt TCP_KEEPCNT: %s\n", strerror(errno));  
        return -1;  
    }  
  
    return 0;  
}
#endif

/******************************************************************************
函数名称：rt_if_up
函数版本：01.01
创建作者：sunxi
创建日期：2020-06-18
函数说明：UP一个接口。
参数说明：
	 if_name： 接口名称，如eth0，fei1等。
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
#if 0
int rt_if_up(int index)
{
	struct ifreq  ifr;
	SOCKET sock;

	if(index >= IF_NUM)
	{
		return -1;
	}

	sock = rt_socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == RT_SOCKET_ERR)
	{
		rt_printf("rt_if_up:: rt_socket::error\n");
		return -1;
	}

	memset(&ifr,0,sizeof(ifr));
	strcpy(ifr.ifr_name,g_if_name[index]);

/*	得到标志*/
	if(rt_sockioctl(sock,SIOCGIFFLAGS,(uint32_t)&ifr) != 0)
	{
		rt_socket_close(sock);
		return -1;
	}

/*	修改标志*/
	ifr.ifr_ifru.ifru_flags |= IFF_UP;

/*	写回标志*/
	if(rt_sockioctl(sock,SIOCSIFFLAGS,(uint32_t)&ifr) != 0)
	{
		rt_socket_close(sock);
		return -1;
	}

	rt_socket_close(sock);
	return 0;
}
#endif

int rt_if_up(int index)
{
	int ret;
	char argv[256] = {0x00};

	sprintf(argv, "/sbin/ifconfig eth%d up", index);

	ret = system(argv);
	
	return ret;

}

/******************************************************************************
函数名称：rt_if_down
函数版本：01.01
创建作者：sunxi
创建日期：2020-06-18
函数说明：DOWN一个接口。
参数说明：
	 if_name： 接口名称，如eth0，fei1等。
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
int rt_if_down(int index)
{
	int ret;
	char argv[256] = {0x00};

	sprintf(argv, "/sbin/ifconfig eth%d down", index);

	ret = system(argv);
	
	return ret;

}

int c2n(char c)
{
	if(c>='0' && c <= '9')
	{
		return c-'0';
	}
	if(c>='A' && c <= 'F')
	{
		return c-'A'+10;
	}
	if(c>='a' && c <= 'f')
	{
		return c-'a'+10;
	}

	return -1;
}

// 将标准MAC地址字符串转换为6字节MAC地址
//80-81-00-b0-32-81
int rt_if_sz2mac(char *sz, unsigned char *mac)
{
	int i;
	int c0,c1;

	if(sz == NULL || mac == NULL)
	{
		return -1;
	}
	
	if(strlen(sz) != 17)
	{
		return -1;
	}

	i=0;
	while(i<17)
	{
		if((i%3 == 2))
		{
			if(sz[i++] != '-')
			{
				return -2;
			}
		}
		
		c0 = c2n(sz[i++]);
		if(c0<0)
		{
			return -3;
		}
		
		c1 = c2n(sz[i++]);
		if(c1<0)
		{
			return -4;
		}
		
		*mac++ = (c0<<4) | c1;
		
	}

	return 0;
}

/*
int rt_if_mac_set(int index, unsigned char *mac)
{
	int ret;
	struct   ifreq   ifr;   
	int   sock;      
  	
	if((unsigned int)index >= IF_NUM)
	{
		return -1;
	}
	
	if(mac == NULL)
	{
		return -1;
	}

	memset(&ifr, 0, sizeof(struct ifreq));

	//创建socket
	sock   =   rt_socket(AF_INET,   SOCK_DGRAM,   0);
	if(sock < 0)
	{   
		rt_printf("Not   create   network   rt_socket   connection\\n");   
		return   (-1);   
	} 

	strncpy(ifr.ifr_name,g_if_name[index],IFNAMSIZ);   
	ifr.ifr_name[IFNAMSIZ   -   1]   =   0; 
		
	//关闭网卡
	ifr.ifr_flags   &=   ~IFF_UP;   	
	if(ioctl(sock,SIOCSIFFLAGS,(uint32_t)&ifr) < 0)
	{   
		//rt_printf("SIOCSIFFLAGS");   
		close(sock);
		return   (-1);   
	} 

	//获取Mac地址
	ret = ioctl(sock,SIOCGIFHWADDR,(uint32_t)&ifr);
	if( ret  <   0)   
	{   
		//rt_printf("Not   setup   SIOCGIFHWADDR(ret=%d)\n",ret);   
		close(sock);
		return   (-1);   
	}   

	//填充Mac地址
	ifr.ifr_hwaddr.sa_data[0]=mac[0];
	ifr.ifr_hwaddr.sa_data[1]=mac[1];
	ifr.ifr_hwaddr.sa_data[2]=mac[2];
	ifr.ifr_hwaddr.sa_data[3]=mac[3];
	ifr.ifr_hwaddr.sa_data[4]=mac[4];
	ifr.ifr_hwaddr.sa_data[5]=mac[5];	
	//修改Mac地址
	ret = ioctl(sock,   SIOCSIFHWADDR,   (uint32_t)&ifr);
	if( ret  <   0)   
	{   
		rt_printf("Not   setup  SIOCSIFHWADDR(ret=%d)\n",ret);   
		close(sock);
		return   (-1); 		
	} 
	
	//启动网卡
	ifr.ifr_flags |= IFF_UP|IFF_RUNNING; 
	if(ioctl(sock,SIOCSIFFLAGS,(uint32_t)&ifr)<0)
	{   
		rt_printf("SIOCSIFFLAGS");   
		close(sock);
		return   (-1);   
	} 

	close(sock);
	
	return 0;
}
*/

int rt_if_mac_set(int index, unsigned char *mac)
{

	char argv[256] = {0x00};
	int ret;
	char NetNum[20]="";

	sprintf(NetNum,"eth%d", index);
	sprintf(argv, "ifconfig %s hw ether %02X:%02X:%02X:%02X:%02X:%02X", NetNum,mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);

#ifdef RT_SOCKET_DEBUG
	rt_printf("sh cmd=%s\r\n",argv);
#endif

	ret = system(argv);

	return ret;



}


int rt_if_mac_get(int index, unsigned char *mac)
{
	int ret;
	struct   ifreq   ifr;   
	int   sock;      

	if((unsigned int)index >= IF_NUM)
	{
		return -1;
	}
	
	if(mac == NULL)
	{
		return -1;
	}
    
	memset(&ifr, 0, sizeof(struct ifreq));

	//创建socket
	sock   =   rt_socket(AF_INET,   SOCK_DGRAM,   0);
	if(sock < 0)
	{   
		rt_printf("Not   create   network   rt_socket   connection\\n");   
		return   (-1);   
	} 

	strncpy(ifr.ifr_name,g_if_name[index],IFNAMSIZ);   
	ifr.ifr_name[IFNAMSIZ   -   1]   =   0; 

	//获取Mac地址
	ret = ioctl(sock,SIOCGIFHWADDR,(uint32_t)&ifr);
	if( ret  <   0)   
	{   
	//	rt_printf("Not   setup   SIOCGIFHWADDR(ret=%d)\n",ret);   
		close(sock);
		return   (-1);   
	}   

	//填充Mac地址
	mac[0] = ifr.ifr_hwaddr.sa_data[0];
	mac[1] = ifr.ifr_hwaddr.sa_data[1];
	mac[2] = ifr.ifr_hwaddr.sa_data[2];
	mac[3] = ifr.ifr_hwaddr.sa_data[3];
	mac[4] = ifr.ifr_hwaddr.sa_data[4];
	mac[5] = ifr.ifr_hwaddr.sa_data[5];	

	close(sock);
	
	return 0;
}




/******************************************************************************
函数名称：rt_if_ip_set
函数版本：01.01
创建作者：sunxi
创建日期：2020-06-18
函数说明：设置一个接口的IP地址。
参数说明：
	 if_name： 接口名称，如eth0，fei1等。
	 ip	： IP地址。
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
int rt_if_ip_set(int index, unsigned char * ip)
{
	int ret;
	char NetNum[20]="";

	if((unsigned int)index >= IF_NUM) 
	{
		return -1;
	}

	sprintf(NetNum,"eth%d",index);

	ret = set_net_param_fun(NetNum," ",ip);   //设置ip

	return ret;
}


/******************************************************************************
函数名称：rt_if_ip_get
函数版本：01.01
创建作者：sunxi
创建日期：2020-06-18
函数说明：得到一个接口的IP地址。
参数说明：
	 if_name： 接口名称，如eth0，fei1等。
	 ip	： 返回的IP地址在*if_addr中。
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
int rt_if_ip_get(int index, unsigned char *ip)
{
	unsigned int addr;
	
	struct ifreq  ifr;
	SOCKET sock;

	if((unsigned int)index >= IF_NUM)
	{
		return -1;
	}
	
	if(ip == NULL)
	{
		return -1;
	}

	sock = rt_socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == RT_SOCKET_ERR)
	{
		rt_printf("%s:: rt_socket [%d]::error\n", __FUNCTION__, index);
		return -1;
	}

	memset(&ifr,0,sizeof(ifr));
	strcpy(ifr.ifr_name,g_if_name[index]);
		
	if(rt_sockioctl(sock,SIOCGIFADDR,(uint32_t)&ifr) != 0)
	{
		rt_socket_close(sock);
		return -1;
	}

	addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
	addr = ntohl(addr);

	memcpy(ip,&addr,4);

	rt_socket_close(sock);
	return 0;
}


/******************************************************************************
函数名称：rt_if_mask_set
函数版本：01.01
创建作者：sunxi
创建日期：2020-06-18
函数说明：设置一个接口的子网屏蔽。
参数说明：
	 if_name： 接口名称，如eth0，fei1等。
	 mask	： 子网屏蔽
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
int rt_if_mask_set(int index, unsigned char * mask)
{
	int ret;
	char NetNum[20]="";

	if((unsigned int)index >= IF_NUM) 
	{
		return -1;
	}

	sprintf(NetNum,"eth%d",index);

	ret = set_net_param_fun(NetNum,"netmask",mask);  //设置子网掩码

	return ret;

}


/******************************************************************************
函数名称：rt_if_mask_get
函数版本：01.01
创建作者：sunxi
创建日期：2020-06-18
函数说明：得到一个接口的子网屏蔽。
参数说明：
	 if_name： 接口名称，如eth0，fei1等。
	 mask	： 返回的子网屏蔽在*if_mask中。
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
int rt_if_mask_get(int index, unsigned char *mask)
{
	unsigned int addr;
	
	struct ifreq  ifr;
	SOCKET sock;

	if((unsigned int)index >= IF_NUM)
	{
		return -1;
	}
	
	if(mask == NULL)
	{
		return -1;
	}

	sock = rt_socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == RT_SOCKET_ERR)
	{
		rt_printf("rt_if_mask_get:: rt_socket::error\n");
		return -1;
	}

	memset(&ifr,0,sizeof(ifr));
	strcpy(ifr.ifr_name,g_if_name[index]);
	
	if(rt_sockioctl(sock,SIOCGIFNETMASK,(uint32_t)&ifr) != 0)
	{
		rt_socket_close(sock);
		return -1;
	}

	addr = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr;
	addr = ntohl(addr);

	memcpy(mask,&addr,4);

	rt_socket_close(sock);
	return 0;
}


/******************************************************************************
函数名称：rt_route_add
函数版本：01.01
创建作者：xxxxxx
创建日期：2008-04-09
函数说明：增加一个接口的路由。
参数说明：
	 destination	： 目标网络。
	 gateway	： 网关
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
int rt_route_add(int index,unsigned char * destination,unsigned char *gateway)
{

	int sock;
	unsigned int destination2,gateway2;
	struct rtentry rt;

	if(destination == NULL || gateway == NULL)
	{
		return -1;
	}

	memcpy(&destination2,destination,4);
	memcpy(&gateway2,gateway,4);


	sock = rt_socket(AF_INET, SOCK_DGRAM, 0);
	if( sock < 0 )
	{
		rt_printf("Create Socket Erro\r\n" );
		return -1;
	}

	memset(&rt,0,sizeof(struct rtentry));

	rt.rt_dev = g_if_name[index];
	rt.rt_flags = RTF_UP  | RTF_GATEWAY;
	
	((struct sockaddr_in *) &rt.rt_gateway)->sin_family = AF_INET;
	((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = htonl(gateway2);
	
	((struct sockaddr_in *) &rt.rt_dst)->sin_family = AF_INET;
	((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = htonl(destination2);

	/* The  netmask  for  the  destination net; ’255.255.255.255’ for a
              host destination and ’0.0.0.0’ for the default route.
	 */
	((struct sockaddr_in *) &rt.rt_genmask)->sin_family = AF_INET;
	((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0 ;

	if( -1 == ioctl(sock,SIOCADDRT,(uint32_t)&rt))
	{
		rt_printf("rt_route_add fail");
		close(sock);
		return -1;
	}

	close(sock);

	return 0;

}

/******************************************************************************
函数名称：rt_route_delete
函数版本：01.01
创建作者：sunxi
创建日期：2020-6-19
函数说明：删除一个接口的路由。
参数说明：
	 if_name_prefic	： 接口名称前缀，如eth，fei等。
	 unit			： 网卡编号，如，0，1，2等
返回值  ：
	>=0		： 成功。
	－1		： 失败。
更新记录：
*/
int rt_route_del(int index,unsigned char * destination,unsigned char *gateway)
{

	int sock;
	unsigned int destination2,gateway2;
	struct rtentry rt;

	if(destination == NULL || gateway == NULL)
	{
		return -1;
	}

	memcpy(&destination2,destination,4);
	memcpy(&gateway2,gateway,4);


	sock = rt_socket(AF_INET, SOCK_DGRAM, 0);
	if( sock < 0 )
	{
		rt_printf("Create Socket Erro\r\n" );
		return -1;
	}

	memset(&rt,0,sizeof(struct rtentry));

	rt.rt_dev = g_if_name[index];
	rt.rt_flags = RTF_UP  | RTF_GATEWAY;
	
//	((struct sockaddr_in *) &rt.rt_gateway)->sin_family = AF_INET;
//	((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = htonl(gateway2);
	
	((struct sockaddr_in *) &rt.rt_dst)->sin_family = AF_INET;
	((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = htonl(destination2);

	/* The  netmask  for  the  destination net; ’255.255.255.255’ for a
              host destination and ’0.0.0.0’ for the default route.
	 */
	((struct sockaddr_in *) &rt.rt_genmask)->sin_family = AF_INET;
	((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0 ;

	if( -1 == ioctl(sock,SIOCDELRT,(uint32_t)&rt))
	{
		rt_printf("rt_route_del fail");
		close(sock);
		return -1;
	}

	close(sock);

	return 0;

}


int net_gateway_set(unsigned char *gateway)
{
	int ret;
	
	char argv_del[] = "/sbin/route del default";
	char argv_add[256] = {0x00};

	if(gateway == 0)
	{
		return -1;
	}

	sprintf(argv_add, "/sbin/route add default gw %d.%d.%d.%d", gateway[0], gateway[1], gateway[2], gateway[3]);

	ret = system(argv_del);
	ret = system(argv_add);
	
	return ret;
}

int net_if_set(int if_index,unsigned char *mac,unsigned char *ip,unsigned char *mask)
{

	if((unsigned int)if_index >= IF_NUM) 
	{
		return -1;
	}

	if(mac)
	{
		rt_if_mac_set(if_index,mac);
	}

	if(ip)
	{
		rt_if_ip_set(if_index,ip);
	}
	
	if(mask)
	{
		rt_if_mask_set(if_index,mask);
	}

	return 0;
}

int net_if_get(int if_index,unsigned char *mac,unsigned char *ip,unsigned char *mask)
{
	int ret;
	char buf[64];
	
	if((unsigned int)if_index >= IF_NUM) 
	{
		return -1;
	}

	if(mac)
	{
		ret = rt_if_mac_get(if_index,mac);
		if(ret != 0)
		{
			return -1;
		}
		sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
	}

	if(ip)
	{
		ret = rt_if_ip_get(if_index,ip);
		if(ret != 0)
		{
			return -2;
		}
		sprintf(buf,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
	}
	
	if(mask)
	{
		ret = rt_if_mask_get(if_index,mask);
		if(ret != 0)
		{
			return -3;
		}
		sprintf(buf,"%d.%d.%d.%d",mask[0],mask[1],mask[2],mask[3]);
	}

	return 0;
}

int rt_get_net_linkstatus(int if_index)
{
	 int skfd = -1; 
	 struct ifreq ifr;  
	unsigned short *data, mii_val;  
	unsigned phy_id;  

	if(if_index < 0)
	{
		return -1;
	}
	
	if (( skfd = rt_socket( AF_INET, SOCK_DGRAM, 0 ) ) < 0 )
	{  
		return -1;
	}  	 
   
 
	/* Get the vitals from the interface. */  
	strncpy(ifr.ifr_name, g_if_name[if_index], IFNAMSIZ);  

	if (ioctl(skfd, SIOCGMIIPHY, (uint32_t)&ifr) < 0)
	{  
		rt_printf( "SIOCGMIIPHY on %s failed!\n",  ifr.ifr_name);  
		close(skfd);
		return -2;  
	}  
  
	   data = (unsigned short  *)(&ifr.ifr_data);  
	   phy_id = data[0];  
	   data[1] = 1;  
  
	if (ioctl(skfd, SIOCGMIIREG, (uint32_t)&ifr) < 0)
	{  
		rt_printf( "SIOCGMIIREG on %s failed!\n", ifr.ifr_name);
		close(skfd);
		return -3;  
	} 
	
	close(skfd);
	
	mii_val = data[3];  
	return(((mii_val & 0x0016) == 0x0004) ? 0 : 1);  	
	
}

#define  NET_NUM_CNT	3	
int rt_get_netcard_id_from_socket(SOCKET s)
{
	struct sockaddr_in local_addr;
	unsigned int len = sizeof(local_addr);
	char buf[32]={0};
	unsigned int ip=0;
	int i ,j;
	int index;

	
	
	rt_getsockname(s, (struct sockaddr *)&local_addr,  &len);		
	
	index = -1;
	for(i=0;i<g_net_num;i++)
	{
		//获取网卡IP
		rt_if_ip_get(i, buf);
		memcpy(&ip, buf, 4);
		if(ip==local_addr.sin_addr.s_addr)
		{
			index = i;
			break;
		}
		else
		{
			for(j=1;j<=NET_NUM_CNT;j++)
			{
				rt_if_ip_get2(i, j, buf);
				memcpy(&ip, buf, 4);
				if(ip==local_addr.sin_addr.s_addr)
				{
					 
					return i;
				}				
			}
		}
			
	}	

	return index;
}


int net_route_set(unsigned char *routenet, unsigned char *routenetmask, unsigned char *routegate)
{
	int ret;
	char buf_routenet[32];
	char buf_routenetmask[32];
	char buf_routegate[32];
	
	char argv_add[512] = {0x00};
	char argv_add2[512] = {0x00};

	if((routenet == 0) || (routenetmask==0) || (routegate==0))
	{
		return -1;
	}

	if((routenet[0]==0) && (routenet[1]==0) && (routenet[2]==0) && (routenet[3]==0))
	{
		return 0;
	}

	if((routegate[0]==0) && (routegate[1]==0) && (routegate[2]==0) && (routegate[3]==0))
	{
		return 0;
	}	

	sprintf(buf_routenet,"%d.%d.%d.%d",routenet[0],routenet[1],routenet[2],routenet[3]);
	sprintf(buf_routenetmask,"%d.%d.%d.%d",routenetmask[0],routenetmask[1],routenetmask[2],routenetmask[3]);
	sprintf(buf_routegate,"%d.%d.%d.%d",routegate[0],routegate[1],routegate[2],routegate[3]);

	sprintf(argv_add, "/sbin/route add -net %s netmask %s gw %s", buf_routenet, buf_routenetmask, buf_routegate);
	sprintf(argv_add2, "/sbin/route add -host %s gw %s", buf_routenet, buf_routegate);

	if((routenetmask[0]==0) && (routenetmask[1]==0) && (routenetmask[2]==0) && (routenetmask[3]==0))
	{
		ret = system(argv_add2);
	}
	else
	{
		ret = system(argv_add);
	}
	return ret;
}

int rt_if_ip_set2(int eth_id, int index, unsigned char *ip)
{
	int ret;
	char NetNum[20]="";

	if((unsigned int)index >= IF_NUM) 
	{
		return -1;
	}

	sprintf(NetNum,"eth%d:%d", eth_id, index);

	ret = set_net_param_fun(NetNum," ",ip);   //设置ip

	return ret;

}

int rt_if_mask_set2(int eth_id, int index, unsigned char *mask)
{
	int ret;
	char NetNum[20]="";

	if((unsigned int)index >= IF_NUM) 
	{
		return -1;
	}

	sprintf(NetNum,"eth%d:%d", eth_id, index);

	ret = set_net_param_fun(NetNum,"netmask",mask);  //设置子网掩码

	return ret;

	
}

int net_if_set2(int eth_id, int if_index,unsigned char *mac,unsigned char *ip,unsigned char *mask)
{

	if((unsigned int)if_index > IF_NUM) 
	{
		return -1;
	}

	if(mac)
	{
		//rt_if_mac_set(if_index,mac);
		mac=mac;
	}

	if(ip)
	{
		rt_if_ip_set2(eth_id, if_index, ip);
	}
	
	if(mask)
	{
		rt_if_mask_set2(eth_id, if_index, mask);
	}

	return 0;
}


int rt_if_ip_get2(int eth_id, int index, unsigned char *ip)
{
	unsigned int addr;
	char buf[32];
	struct ifreq  ifr;
	SOCKET sock;

	if((unsigned int)eth_id >= IF_NUM)
	{
		return -1;
	}
	
	if(ip == NULL)
	{
		return -1;
	}

	sock = rt_socket(AF_INET, SOCK_DGRAM, 0);
	if (sock == RT_SOCKET_ERR)
	{
		rt_printf("%s:: rt_socket [%d][%d]::error\n", __FUNCTION__, eth_id, index);
		return -1;
	}

	sprintf(buf, "eth%d:%d", eth_id, index);
	memset(&ifr,0,sizeof(ifr));
	strcpy(ifr.ifr_name,buf);
		
	if(rt_sockioctl(sock,SIOCGIFADDR,(uint32_t)&ifr) != 0)
	{
		rt_socket_close(sock);
		return -1;
	}

	addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
	addr = ntohl(addr);

	memcpy(ip,&addr,4);

	rt_socket_close(sock);
	return 0;
}

int rt_if_down2(int eth_id, int index)
{
	int ret;
	char argv[256] = {0x00};

	sprintf(argv, "/sbin/ifconfig eth%d:%d down", eth_id, index);

	ret = system(argv);
	
	return ret;
}


/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/



/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/

#define IF_INDEX 	1
int net_if_test(void)
{
	//uint32_t us0;
	unsigned char mac[6];
	unsigned char ip[4];
	unsigned char mask[4];
	unsigned char gateway[4];

	rt_printf("net_if_test begin...\r\n");

	// 得到并打印旧的网络参数
	net_if_get(IF_INDEX,mac,ip,mask);
	rt_printf("old mac: %02x:%02x:%02x:%02x:%02x:%02x\r\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
	rt_printf("old ip:%d.%d.%d.%d\r\n",ip[0],ip[1],ip[2],ip[3]);
	rt_printf("old mask:%d.%d.%d.%d\r\n",mask[0],mask[1],mask[2],mask[3]);
	rt_printf("old gateway:%d.%d.%d.%d\r\n",gateway[0],gateway[1],gateway[2],gateway[3]);

	// 设置接口MAC地址
	mac[0] = 'H';
	mac[1] = 'G';
	mac[2] = 192;
	mac[3] = 168;
	mac[4] = 1;
	mac[5] = 240;
	
	// 设置IP
	memcpy(ip,mac+2,4);
	
	// 设置MASK
	mask[0] = 255;
	mask[1] = 255;
	mask[2] = 0;
	mask[3] = 0;

	// 设置网关
	gateway[0] = 192;
	gateway[1] = 168;
	gateway[2] = 1;
	gateway[3] = 254;

	// 设置网络参数
	//us0 = ustimer_get_origin();
	net_if_set(IF_INDEX,mac,ip,mask);
	net_gateway_set(gateway);
	//rt_printf("net_if_set duration:%dus.\r\n",ustimer_get_duration(us0));

	// 得到并打印新的网络参数
	net_if_get(IF_INDEX,mac,ip,mask);
	rt_printf("new mac: %02x:%02x:%02x:%02x:%02x:%02x\r\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
	rt_printf("new ip:%d.%d.%d.%d\r\n",ip[0],ip[1],ip[2],ip[3]);
	rt_printf("new mask:%d.%d.%d.%d\r\n",mask[0],mask[1],mask[2],mask[3]);
	rt_printf("new gateway:%d.%d.%d.%d\r\n",gateway[0],gateway[1],gateway[2],gateway[3]);

	rt_printf("net_if_test ok\r\n");
	
	return 0;
}

 
int socket_test(void)
{
	unsigned char buf[512];
	SOCKET sock, new_fd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int sin_size, portnumber;
	char hello[] = "Hello! Are You Fine?\n";

	portnumber = 1111;

	/*服务器端开始建立socket描述符*/
	if ((sock = rt_socket(AF_INET, SOCK_STREAM, 0)) == RT_SOCKET_ERR)
	{
		rt_printf ("Socket error:%d\n\a", sock);
	}

	/*服务器端填充sockaddr结构*/
	memset (&server_addr, 0, sizeof (struct sockaddr_in));//将
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
	server_addr.sin_port = htons (portnumber);

	/*捆绑sock描述符*/
	if (rt_bind (sock, (struct sockaddr *)(&server_addr), sizeof (struct sockaddr)) == -1)
	{
		rt_printf ("Bind error:%d\n\a", sock);
	}

	/*监听sock描述符*/
	if (rt_listen (sock, 5) == -1)
	{
		rt_printf ("Listen error:%d\n\a", sock);
	}

	while(1)
	{
		/*服务器阻塞，直到客户程序建立连接*/
		sin_size = sizeof (struct sockaddr_in);
		if ((new_fd = rt_accept (sock, (struct sockaddr*)(&client_addr), &sin_size)) == RT_SOCKET_ACCEPT_RST)
		{
			rt_printf ("Accept error:%d\n\a", sock);
		}

		rt_printf ("Server get connection from %d\n", new_fd);
		if (rt_send(new_fd, hello, strlen(hello),0) == -1)
		{
			rt_printf ("Write Error:%d\n", new_fd);
		}
 
		while(1)
		{
			int flag;
			if ((flag = rt_recv (new_fd, buf, 512, 0)) < 0)
			{
				rt_printf ("Reading data error!\n");
				break;
			}

			if (flag == 0)
			{
				rt_printf ("Ending current connection!\n");
				break;
			}
			else
			{
				rt_printf("-->%s\n", buf);
				if (strstr (buf, "exit"))
				{
					rt_printf ("Ending current connection!\n");
					break;
				}
			}
			rt_socket_close (new_fd);
		}
		rt_socket_close (sock);
	}
	
	return 0;
}


/*------------------------------ 文件结束 -------------------------------------
*/

