1. ip地址、子网掩码、网关设置和获取

net.h

/*
 * =====================================================================================
 *
 *       Filename:  net.h
 *
 *    Description: 
 *
 *        Version:  1.0
 *        Created:  07/22/17 16:13:58
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  linsheng.pan (), life_is_legend@163.com
 *   Organization: 
 *
 * =====================================================================================
 */
#ifndef INCLUDE_NET_H
#define INCLUDE_NET_H
#ifdef __cplusplus
extern "C" {
#endif



#include <net/if.h>


#define WV_NET_SUCCESS    (0)
#define WV_NET_ERROR      (-1)


/*
* function: 获取本机指定网卡的IP
*
* description: Net_GetIpAddr
*
* input:  @eth_name: 网卡的名字
*         @ip: ip的网络序号
*         @buf_size: 字符串的长度
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_GetIpAddr(const char *eth_name, unsigned int *ip, int ip_len);


/*
* function: 获取本机指定网卡的IP
*
* description: Net_SetIpAddr
*
* input:  @eth_name: 网卡的名字
*         @ip_addr: ip的网络序号
*        
* output: @
*
* return:
*
* author: linsheng.pan
*/


int Net_SetIpAddr(const char *eth_name, const unsigned int ip_addr);


/*
* function: Net_SetIpAddrStr
*
* description: 设置网卡的IP
*
* input:  @eth_name:网卡名
*         @ip_buf:ip地址("192.168.1.1")
*         @buf_size: ip地址的长度
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_SetIpAddrStr(const char *eth_name, const char *ip_buf, int buf_size);


/*
* function: Net_SetIpAddrStr
*
* description: 设置网卡的IP
*
* input:  @eth_name:网卡名
*         @ip_buf:ip地址("192.168.1.1")
*         @buf_size: ip地址的长度
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_GetIpAddrStr(const char *eth_name, char *ip_buf, int buf_size);



/*
* function: Net_GetMacAddr
*
* description: 获取本机指定网卡的MAC地址
*
* input:  @eth_name: 网卡名字
*         @mac_buf: 存储mac地址
*         @buf_size: mac地址的长度
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_GetMacAddr(const char *eth_name, unsigned char *mac_buf, int buf_size);



/*
* function: Net_SetMacAddr
*
* description:给指定网卡设置mac地址
*
* input:  @eth_name:网卡名
*         @mac_buf:mac地址
*         @buf_size:mac地址长度
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_SetMacAddr(const char *eth_name, const unsigned char *mac_buf, int buf_size);



/*
* function: Net_BindInterface
*
* description: 将套接字绑定网卡
*
* input:  @sockfd: 一个已经打开的套接字
*         @eth_name: 网卡名字
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_BindInterface(int *sockfd, const char *eth_name);



/*
* function: Net_GetIpAddrWithDHCP
*
* description: 动态获取ip
*
* input:  @ip: ip的网络序
*         @eth_name: 网卡名字
*
* output: @
*
* return:
*
* author: linsheng.pan
*/


int Net_GetIpAddrWithDHCP(const char * eth_name, unsigned int *ip, unsigned int ip_len);



/*
* function: Net_SetNetmask
*
* description: 设置子网掩码
*
* input:  @eth_name: 网口名
*         @net_mask: 网络序
*
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_SetNetmask(const char *eth_name, const unsigned int net_mask);






/*
* function: Net_GetNetmask
*
* description: 获取子网掩码
*
* input:  @eth_name: 网口名
*
* output: @net_mask: 网络序存储
*         @net_mask_len: 长度
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_GetNetmask(const char *eth_name, unsigned int *net_mask, int net_mask_len);


/*
* function: Net_SetGateWay
*
* description: 设置网关
*
* input:  @eth_name: 网口名
*         @gw: 网络序
*
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_SetGateWay(char *eth_name, unsigned int gw);


/*
* function: Net_DelGateWay
*
* description: 删除网关
*
* input:  @eth_name: 网口名
*         @gw: 网络序
*
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/


int Net_DelGateWay(char *eth_name, unsigned int gw);


/*
* function: Net_GetGateWay
*
* description: 获取网关
*
* input:  @eth_name: 网口名
*         @gateway: 网络序
*         @buf_len: 缓存区长度
*       
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/


int Net_GetGateWay(const char *eth_name,  unsigned int *gateway, int buf_len);


#ifdef __cplusplus
}
#endif
#endif /* ifndef INCLUDE_NET_H */

net.c

/*
 * =====================================================================================
 *
 *       Filename:  net.c
 *
 *    Description: 
 *
 *        Version:  1.0
 *        Created:  07/22/17 16:32:49
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  linsheng.pan (), life_is_legend@163.com
 *   Organization: 
 *
 * =====================================================================================
 */
#include "wv_net.h"


#include "wv_log.h"


#include <arpa/inet.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <net/if.h> 
#include <net/route.h> 
#include <net/if_arp.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <linux/rtnetlink.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/utsname.h>
#include <limits.h>
#include <linux/sockios.h>


#define BUFSIZE   (8192)


#define MAX_NETWORK_NUM         (16)


#define ERR_BUF_LEN         (256)
#define ERR_STRING(err_buf)   strerror_r(errno, err_buf, sizeof(err_buf))


#define CLOSE(fd)  {
    if(fd > 0) 
    {
            close(fd);
            fd = -1;
    }
}


struct route_info {
    u_int dstAddr;
    u_int srcAddr;
    u_int gateWay;
    char ifName[IF_NAMESIZE];
};


static struct ifconf s_stIfconf;
static struct ifreq s_st_arrIfreq[MAX_NETWORK_NUM];


static int Net_FindInterface(const char *eth_name)
{
    if(!eth_name)
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    int index = -1;
    int interface_num = 0;
    interface_num = s_stIfconf.ifc_len / sizeof(struct ifreq);


    while(interface_num-- > 0)
    {
        if(!strcmp(s_st_arrIfreq[interface_num].ifr_name, eth_name))
        {
            index = interface_num;
            break;
        }
    }


    return index;
}


/*
* function: Net_GetInterfaceInfo
*
* description: 获取所有工作网卡的信息(网)
*
* input:  @
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
static int Net_GetInterfaceInfo(void)
{
    char err_buf[ERR_BUF_LEN] = {0};
    int sockfd = -1;
    int interface_num = 0;


    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ERR_STRING(err_buf);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: %s", err_buf);


        return WV_NET_ERROR;
    }


    s_stIfconf.ifc_len = sizeof(s_st_arrIfreq);
    s_stIfconf.ifc_buf = (caddr_t)(s_st_arrIfreq);


    if(!ioctl(sockfd, SIOCGIFCONF, &s_stIfconf))
    {
        interface_num = s_stIfconf.ifc_len / sizeof(struct ifreq);


        while(interface_num-- > 0)
        {
            //get mac ip broatcast subnet mask
            //if(!ioctl(sockfd, SIOCGIFFLAGS | SIOCGIFHWADDR | SIOCGIFADDR | SIOCGIFBRDADDR | SIOCGIFNETMASK, &s_st_arrIfreq[interface_num]))
            if(!ioctl(sockfd,  SIOCGIFADDR , &s_st_arrIfreq[interface_num]))
            {
                //LOG_PRINTF(LOG_LEVEL_DEBUG, LOG_MODULE_SYS, "Get Network[%d] Info Success!", interface_num);
            }
            else
            {
                ERR_STRING(err_buf);
                LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: %s", err_buf);


                CLOSE(sockfd);
                return WV_NET_ERROR;
            }
        }
    }
    else
    {
        ERR_STRING(err_buf);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: %s", err_buf);


        CLOSE(sockfd);
        return WV_NET_ERROR;


    }


    CLOSE(sockfd);


    return WV_NET_SUCCESS;
}



/*
* function: Net_SetIpAddrStr
*
* description: 设置网卡的IP
*
* input:  @eth_name:网卡名
*         @ip_buf:ip地址("192.168.1.1")
*         @buf_size: ip地址的长度
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_SetIpAddrStr(const char *eth_name, const char *ip_buf, int buf_size)
{
    U32 u32IPAddr = 0;
    inet_pton(AF_INET, ip_buf, &u32IPAddr);


    return Net_SetIpAddr(eth_name, u32IPAddr);
}



/*
* function: 获取本机指定网卡的IP
*
* description: Net_GetIpAddr
*
* input:  @eth_name: 网卡的名字
*         @ip_buf: ip的字符串
*         @buf_size: 字符串的长度
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_GetIpAddrStr(const char *eth_name, char *ip_buf, int buf_size)
{
    if((!eth_name) || (!ip_buf))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }

    int index = -1;


    //获取本地网卡信息
    Net_GetInterfaceInfo();
    //判断是否有指定网口的ip
    if((index = Net_FindInterface(eth_name)) >= 0)
    {
        //将ip的网络序转换为点十制
        inet_ntop(AF_INET, &(((struct sockaddr_in *)&(s_st_arrIfreq[index].ifr_addr))->sin_addr.s_addr), ip_buf, buf_size);
        LOG_PRINTF(LOG_LEVEL_DEBUG, LOG_MODULE_SYS, "%s : %s", eth_name, ip_buf);
    }
    else
    {
        //解锁资源并推出
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: Can't find %s", eth_name);
        return WV_NET_ERROR;
    }


    return WV_NET_SUCCESS;
}


/*
* function: 获取本机指定网卡的IP
*
* description: Net_GetIpAddr
*
* input:  @eth_name: 网卡的名字
*         @ip: 网络序
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_GetIpAddr(const char *eth_name, unsigned int *ip, int ip_len)
{
    if((!eth_name) || (!ip))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }

    int index = -1;
    char ip_buf[16] = {0};
    unsigned int val = 0;


    //获取本地网卡信息
    Net_GetInterfaceInfo();
    //判断是否有指定网口的ip
    if((index = Net_FindInterface(eth_name)) >= 0)
    {
        //将ip的网络序转换为点十制
        inet_ntop(AF_INET, &(((struct sockaddr_in *)&(s_st_arrIfreq[index].ifr_addr))->sin_addr.s_addr), ip_buf, sizeof(ip_buf));
        memcpy(&val, &(((struct sockaddr_in *)&(s_st_arrIfreq[index].ifr_addr))->sin_addr.s_addr), sizeof(val));
        *ip = val;
        //LOG_PRINTF(LOG_LEVEL_DEBUG, LOG_MODULE_SYS, "Get ip[%s] : %s", eth_name, ip_buf);
    }
    else
    {
        //解锁资源并推出
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: Can't find %s", eth_name);
        return WV_NET_ERROR;
    }


    return WV_NET_SUCCESS;
}



/*
* function: Net_SetIpAddr
*
* description: 设置ip
*
* input:  @eth_name: 网口名(eth0, eth0:0),可以创建虚拟网口
*         @ip_addr: 网络序
*         @ip_len: 长度
*
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_SetIpAddr(const char *eth_name, const unsigned int ip_addr)
{
    if((!eth_name))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    int fd; 
    struct ifreq ifr;  
    struct sockaddr_in *sin; 
    char err_buff[ERR_BUF_LEN];
    unsigned int ip_net = 0;
    ip_net = ip_addr;
    char *ip_str = NULL;
    struct in_addr net_addr;


    fd = socket(AF_INET, SOCK_DGRAM, 0); 
    if(fd < 0) 
    { 
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call socket failed[%s]", err_buff);
        return WV_NET_ERROR;      
    } 


    memset(&ifr,0,sizeof(ifr));  
    strncpy(ifr.ifr_name, eth_name, strlen(eth_name));  
    sin = (struct sockaddr_in*)&ifr.ifr_addr;      
    sin->sin_family = AF_INET;      
    memcpy(&(sin->sin_addr), &ip_net, sizeof(ip_net));


    if(ioctl(fd, SIOCSIFADDR, &ifr) < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call ioctl failed[%s]", err_buff);
        CLOSE(fd);
        return WV_NET_ERROR;
    }


    CLOSE(fd);


    return WV_NET_SUCCESS;
}


/*
* function: Net_GetMacAddr
*
* description: 输入网口名字,获取mac地址
*
* input:  @eht_name: 网口名字("eth0")
*
* output: @mac_buf: 存储mac地址的buffer(6 字节以上)
*         @mac_len: buffer 长度
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_GetMacAddr(const char *eth_name, unsigned char *mac_buf, int mac_len)
{
    if((!eth_name) || (!mac_buf))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    struct ifreq temp;
    struct sockaddr *addr;
    int fd = -1;
    char err_buff[ERR_BUF_LEN];
    int err_code = WV_NET_SUCCESS;
    int ret = 0;


    if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call socket failed[%s]", err_buff);
        return WV_NET_ERROR;
    }


    strncpy(temp.ifr_name, eth_name, strlen(eth_name) + 1);
    addr = (struct sockaddr *)(&temp.ifr_hwaddr);
    addr->sa_family = ARPHRD_ETHER;


    ret = ioctl(fd, SIOCGIFHWADDR, &temp);
    if(ret < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call ioctl failed[%s]", err_buff);
        err_code = WV_NET_ERROR;
    }

    close(fd);


    if(WV_NET_SUCCESS == err_code)
    {
        memcpy(mac_buf, addr->sa_data, 6);
        //LOG_PRINTF(LOG_LEVEL_DEBUG, LOG_MODULE_SYS, "Get [%s], mac:%x:%x:%x:%x:%x:%x", eth_name, mac_buf[0],
        //        mac_buf[1], mac_buf[2], mac_buf[3], mac_buf[4], mac_buf[5]);
    }

    return err_code;
}



/*
* function: Net_SetMacAddr
*
* description:   设置mac地址
*
* input:  @eth_name: 网口名
*         @mac_buff: mac地址(0xa0,0x69,0x86,0x0, 0x0, 0x1)
*         @mac_len:  buffer 长度
*
*
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_SetMacAddr(const char *eth_name, const unsigned char *mac_buff, int mac_len)
{
    if((!eth_name) || (!mac_buff))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    struct ifreq temp;
    struct sockaddr *addr;
    int fd = -1;
    char err_buff[ERR_BUF_LEN];
    int err_code = WV_NET_SUCCESS;
    int ret = 0;



    strncpy(temp.ifr_name, eth_name, strlen(eth_name) + 1);
    //ifconfig down
    temp.ifr_flags &= ~IFF_UP;


    if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call socket failed[%s]", err_buff);
        return WV_NET_ERROR;
    }


    ret = ioctl(fd, SIOCSIFFLAGS, &temp);
    if(ret < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call ioctl failed[%s]", err_buff);
        CLOSE(fd);
        return  WV_NET_ERROR;
    }


    CLOSE(fd);



    //set mac
    if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call socket failed[%s]", err_buff);
        return WV_NET_ERROR;
    }


    addr = (struct sockaddr *)(&temp.ifr_hwaddr);
    addr->sa_family = ARPHRD_ETHER;
    memcpy(addr->sa_data, mac_buff, mac_len);


    ret = ioctl(fd, SIOCSIFHWADDR, &temp);
    if(ret < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call ioctl failed[%s]", err_buff);
        CLOSE(fd);
        return WV_NET_ERROR;
    }


    CLOSE(fd);

    //ifconfig up
    temp.ifr_flags |= IFF_UP;


    if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call socket failed[%s]", err_buff);
        return WV_NET_ERROR;
    }


    ret = ioctl(fd, SIOCSIFFLAGS, &temp);
    if(ret < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call ioctl failed[%s]", err_buff);
        CLOSE(fd);
        return  WV_NET_ERROR;
    }


    CLOSE(fd);


    LOG_PRINTF(LOG_LEVEL_DEBUG, LOG_MODULE_SYS, "Set [%s], mac:%x:%x:%x:%x:%x:%x", eth_name, mac_buff[0],
                mac_buff[1], mac_buff[2], mac_buff[3], mac_buff[4], mac_buff[5]);



    return err_code;
}



/*
* function: Net_GetNetmask
*
* description: 获取子网掩码
*
* input:  @eth_name: 网口名
*
* output: @net_mask: 主机序存储
*         @net_mask_len: 长度
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_GetNetmask(const char *eth_name, unsigned int *net_mask, int net_mask_len)
{
    if((!eth_name) || (!net_mask))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    int fd; 
    struct ifreq ifr;  
    struct sockaddr_in *sin; 
    char err_buff[ERR_BUF_LEN];
    unsigned int net_mask_tmp = 0;
    char *ip_str = NULL;
    struct in_addr net_addr;


    fd = socket(AF_INET, SOCK_DGRAM, 0); 
    if(fd < 0) 
    { 
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call socket failed[%s]", err_buff);
        return WV_NET_ERROR;      
    } 


    memset(&ifr,0,sizeof(ifr));  
    strncpy(ifr.ifr_name, eth_name, strlen(eth_name));  
    sin = (struct sockaddr_in*)&ifr.ifr_addr;      
    sin->sin_family = AF_INET;      


    if(ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call ioctl failed[%s]", err_buff);
        CLOSE(fd);
        return WV_NET_ERROR;
    }


    memcpy(&net_mask_tmp, &(sin->sin_addr), net_mask_len);

    *net_mask = net_mask_tmp;


    CLOSE(fd);


    return WV_NET_SUCCESS;
}




/*
* function: Net_SetNetmask
*
* description: 设置子网掩码
*
* input:  @eth_name: 网口名
*         @net_mask: 网络序
*         @net_mask_len: 长度
*
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_SetNetmask(const char *eth_name, const unsigned int net_mask)
{
    if((!eth_name))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    int fd; 
    struct ifreq ifr;  
    struct sockaddr_in *sin; 
    char err_buff[ERR_BUF_LEN];
    struct in_addr net_addr;
    char *ip_str = NULL;
    unsigned int net_mask_net= net_mask;


    fd = socket(AF_INET, SOCK_DGRAM, 0); 
    if(fd < 0) 
    { 
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call socket failed[%s]", err_buff);
        return WV_NET_ERROR;      
    } 


    memset(&ifr,0,sizeof(ifr));  
    strncpy(ifr.ifr_name, eth_name, strlen(eth_name));  
    sin = (struct sockaddr_in*)&ifr.ifr_addr;      
    sin->sin_family = AF_INET;      
    memcpy(&(sin->sin_addr), &net_mask_net, sizeof(net_mask_net));


    if(ioctl(fd, SIOCSIFNETMASK, &ifr) < 0)
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call ioctl failed[%s]", err_buff);
        CLOSE(fd);
        return WV_NET_ERROR;
    }


    CLOSE(fd);


    return WV_NET_SUCCESS;
}



/*
* function: Net_BindInterface
*
* description: 将套接字绑定网卡
*
* input:  @sockfd: 一个已经打开的套接字
*         @eth_name: 网卡名字
*
* output: @
*
* return:
*
* author: linsheng.pan
*/
int Net_BindInterface(int *sockfd, const char *eth_name)
{
    if((!eth_name) && (!sockfd))
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    int ret = 0;
    char err_buf[ERR_BUF_LEN] = {0};
    struct ifreq netdev;
    memset(&netdev, 0, sizeof(netdev));
    strncpy(netdev.ifr_name, eth_name, sizeof(netdev.ifr_name) - 1);


    ret = setsockopt(*sockfd, SOL_SOCKET, SO_BINDTODEVICE, &netdev, sizeof(netdev));


    if(ret)
    {
        ERR_STRING(err_buf);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: call setsockopt:%s", err_buf);


        return WV_NET_ERROR;
    }


    return WV_NET_SUCCESS;
}



/*
* function: Net_GetIpAddrWithDHCP
*
* description: 动态获取IP
*
* input:  @
*
* output: @
*
* return@
* success:
*    fail:
*
* author: linsheng.pan
*/
int Net_GetIpAddrWithDHCP(const char * eth_name, unsigned int *ip, unsigned int ip_len)
{
    if(!eth_name)
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: param = NULL");
        return WV_NET_ERROR;
    }


    char cmd[128] = {0};
    //尝试5次获取动态ip,失败后自动退出
    snprintf(cmd, sizeof(cmd), "udhcpc -t 5 -n -i %s", eth_name);
    system(cmd);


    Net_GetIpAddr(eth_name, ip, ip_len);


    return WV_NET_SUCCESS;
}




int Net_SetGateWay(char *eth_name, unsigned int gw)   
{   
    if(!eth_name)
    {
        return WV_NET_ERROR;
    }

    int skfd;   
    struct rtentry rt;   
    int err;  
    char ip_str[16];
    char err_buff[ERR_BUF_LEN] = {0};


    skfd = socket(PF_INET, SOCK_DGRAM, 0);   
    if (skfd < 0)   
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "ERROR[%s]: call socket", err_buff);
        return WV_NET_ERROR;   
    }


    /* Delete existing defalt gateway */   
    memset(&rt, 0, sizeof(rt));   


    rt.rt_dst.sa_family = AF_INET;   
    ((struct sockaddr_in *)&rt.rt_dst)->sin_addr.s_addr = 0;   


    rt.rt_genmask.sa_family = AF_INET;   
    ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = 0;   


    rt.rt_flags = RTF_UP;   
    rt.rt_dev = eth_name;


    err = ioctl(skfd, SIOCDELRT, &rt);   


    if ((err == 0 || errno == ESRCH) && gw)
    {   
        /* Set default gateway */   
        memset(&rt, 0, sizeof(rt));   


        rt.rt_dst.sa_family = AF_INET;   
        ((struct sockaddr_in *)&rt.rt_dst)->sin_addr.s_addr = 0;   


        rt.rt_gateway.sa_family = AF_INET;   
        ((struct sockaddr_in *)&rt.rt_gateway)->sin_addr.s_addr = gw;   


        rt.rt_genmask.sa_family = AF_INET;   
        ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = 0;   


        rt.rt_flags = RTF_UP | RTF_GATEWAY;   
        rt.rt_dev = eth_name;


        err = ioctl(skfd, SIOCADDRT, &rt);   
    }


    inet_ntop(AF_INET, &gw, ip_str, sizeof(ip_str));
    if(!(err == 0 || errno == ESRCH))
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error[%s]: Can't set %s:%s gate way",err_buff, eth_name, ip_str);
    }
    else
    {
        LOG_PRINTF(LOG_LEVEL_DEBUG, LOG_MODULE_SYS, "Set default gateway %s:%s ", eth_name, ip_str);
    }



    CLOSE(skfd);   


    return err;   
}   



int Net_DelGateWay(char *eth_name, unsigned int gw)   
{   
    if(!eth_name)
    {
        return WV_NET_ERROR;
    }

    int skfd;   
    struct rtentry rt;   
    int err;  
    char ip_str[16];
    char err_buff[ERR_BUF_LEN] = {0};


    skfd = socket(PF_INET, SOCK_DGRAM, 0);   
    if (skfd < 0)   
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "ERROR[%s]: call socket", err_buff);
        return WV_NET_ERROR;   
    }


    /* Delete existing defalt gateway */   
    memset(&rt, 0, sizeof(rt));   


    rt.rt_dst.sa_family = AF_INET;   
    ((struct sockaddr_in *)&rt.rt_dst)->sin_addr.s_addr = 0;  


    rt.rt_gateway.sa_family = AF_INET;   
    ((struct sockaddr_in *)&rt.rt_gateway)->sin_addr.s_addr = gw;


    rt.rt_genmask.sa_family = AF_INET;   
    ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = 0;   


    rt.rt_flags = RTF_UP;   
    rt.rt_dev = eth_name;


    err = ioctl(skfd, SIOCDELRT, &rt);  


    inet_ntop(AF_INET, &gw, ip_str, sizeof(ip_str));
    if(!(err == 0 || errno == ESRCH))
    {
        ERR_STRING(err_buff);
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error[%s]: Can't del %s:%s gate way",err_buff, eth_name, ip_str);
    }
    else
    {
        LOG_PRINTF(LOG_LEVEL_DEBUG, LOG_MODULE_SYS, "Del default gateway %s:%s ", eth_name, ip_str);
    }



    CLOSE(skfd);   


    return err;   
}




int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId)
{
    struct nlmsghdr *nlHdr;
    int readLen = 0, msgLen = 0;
    do{
        if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0)
        {
            perror("SOCK READ: ");
            return WV_NET_ERROR;
        }


        nlHdr = (struct nlmsghdr *)bufPtr;
        if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR))
        {
            perror("Error in recieved packet");
            return WV_NET_ERROR;
        }
        if(nlHdr->nlmsg_type == NLMSG_DONE)
        {
            break;
        }
        else
        {
            bufPtr += readLen;
            msgLen += readLen;
        }
        if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0)
        {
            break;
        }
    } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));
    return msgLen;
}


int parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo)
{
    struct rtmsg *rtMsg;
    struct rtattr *rtAttr;
    int rtLen;
    struct in_addr dst;
    struct in_addr gate;
    rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);
    // If the route is not for AF_INET or does not belong to main routing table
    //then return.
    if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
    {
        return WV_NET_ERROR;
    }


    rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
    rtLen = RTM_PAYLOAD(nlHdr);
    for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)){
        switch(rtAttr->rta_type) {
            case RTA_OIF:
                if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
                break;
            case RTA_GATEWAY:
                rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);
                break;
            case RTA_PREFSRC:
                rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);
                break;
            case RTA_DST:
                rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);
                break;
        }
    }


    unsigned int ip_addr = 0;
    char ip_str[16];
    ip_addr = rtInfo->dstAddr;
    inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str));

    if (strstr(ip_str, "0.0.0.0"))
    {
        return 0;
    }
    else
    {
        return WV_NET_ERROR;
    }
}


int Net_GetGateWay(const char *eth_name,  unsigned int *gateway, int buf_len)
{
    if((!eth_name) || (!gateway) ||( buf_len < 4))
    {
        return WV_NET_ERROR;
    }


    struct nlmsghdr *nlMsg;
    struct rtmsg *rtMsg;
    struct route_info stRouteInfo;
    char msgBuf[BUFSIZE];


    int sock, len, msgSeq = 0;
    int ret = 0;


    if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
    {
        perror("Socket Creation: ");
        return WV_NET_ERROR;
    }


    memset(msgBuf, 0, BUFSIZE);
    nlMsg = (struct nlmsghdr *)msgBuf;
    rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);
    nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
    nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .
    nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
    nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet.
    nlMsg->nlmsg_pid = getpid(); // PID of process sending the request.
    if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0)
    {
        printf("Write To Socket Failed…
");
        return WV_NET_ERROR;
    }


    if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0)
    {
        printf("Read From Socket Failed…
");
        return WV_NET_ERROR;
    }


    for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len))
    {
        memset(&stRouteInfo, 0, sizeof(struct route_info));
        ret = parseRoutes(nlMsg, &stRouteInfo);
        if(0 != ret)
        {
            continue;
        }


        //比较eth_name
        if(0 == strcmp(eth_name, stRouteInfo.ifName))
        {
            *gateway = stRouteInfo.gateWay;
            break;
        }
        else
        {
            ret = WV_NET_ERROR;
        }
    }


    if(ret < 0)
    {
        LOG_PRINTF(LOG_LEVEL_ERROR, LOG_MODULE_SYS, "Error: Can't get %s: gate way", eth_name);
    }


    close(sock);
    return ret;
}