net_network.cpp
#include <net/if.h>
#include <net/if_arp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <stdbool.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/route.h>
#include "net_network.h"
//#define ENABLE_NET_WORK_DBG
#ifdef ENABLE_NET_WORK_DBG
#define NET_ERR(...) printf(__VA_ARGS__)
#define NET_WAR(...) printf(__VA_ARGS__)
#define NET_DBG(...) printf(__VA_ARGS__)
#else
#define NET_ERR(...) printf(__VA_ARGS__)
#define NET_WAR(...) printf(__VA_ARGS__)
#define NET_DBG(...)
#endif
#if 0
/**
*data dump
*@param buf_name -in- the dumped buffer name
*@param buffer -in- the buffer need be dumped
*@input_len -in- the length need be dumped
*/
static void data_dump(char *buf_name, char *buffer, int input_len)
{
int i = 0;
if (!buf_name || !buffer)
{
NET_ERR("the buf_name or buffer is NULL\n");
return;
}
NET_DBG("The %s: dump as below:\n", buf_name);
for (i = 0; i < input_len; i++)
{
NET_DBG("%02x", buffer[i]);
if ((i + 1) % 16 == 0)
{
NET_DBG("\n");
}
}
}
#endif
/**
* for example: 0AC8A8C0 -> 0xac8a8c0 (char -> unsigned long)
* This a internal function, I only used it in get_route_table. So I can confirm
* the buffer is long enough.
* change the char to sockaddr
*@param buffer -in- the buffer wanted to change
*@param sockaddr_buf -out- the sockaddr store the address
*@return the number which converts successfully
*/
static int change_char_to_sockaddr(char *buffer, struct sockaddr *sockaddr_buf)
{
char *sp = buffer, *bp;
unsigned int i;
unsigned val;
struct sockaddr_in *sin;
sin = (struct sockaddr_in *) sockaddr_buf;
sin->sin_family = AF_INET;
sin->sin_port = 0;
val = 0;
bp = (char *) &val;
for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++)
{
*sp = toupper(*sp);
if ((*sp >= 'A') && (*sp <= 'F'))
{
bp[i] |= (int)(*sp - 'A') + 10;
}
else if ((*sp >= '0') && (*sp <= '9'))
{
bp[i] |= (int)(*sp - '0');
}
else
{
return (-1);
}
bp[i] <<= 4;
sp++;
*sp = toupper(*sp);
if ((*sp >= 'A') && (*sp <= 'F'))
{
bp[i] |= (int)(*sp - 'A') + 10;
}
else if ((*sp >= '0') && (*sp <= '9'))
{
bp[i] |= (int)(*sp - '0');
}
else
{
return (-1);
}
sp++;
}
sin->sin_addr.s_addr = htonl(val);
return (sp - buffer);
}
/**
************************
* The APIs of ifconfig *
************************
*/
int get_if_dev_name(ifr_name_t *ifr_names, unsigned int input_len, int *dev_nums)
{
FILE *fp = NULL;
char buffer[4096] = {0};
char *dev_name = NULL;
char *tmp = NULL;
int ret = SUCCESS;
int i = 0;
if (!ifr_names || input_len < (IF_DEV_NUM_MAX * sizeof(ifr_name_t)) || !dev_nums)
{
NET_ERR("%s: Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
fp = fopen(NET_DEV_NAME, "r");
if (!fp)
{
NET_ERR("%s: open the net device failed. errno: %s\n", __func__, strerror(errno));
ret = ERR_NOTEXIST;
goto ERROR0;
}
for (i = 0; fgets(buffer, 4096, fp); i++)
{
NET_DBG("buffer is: %s\n", buffer);
/*drop the first and second line*/
if (i < 2)
{
continue;
}
tmp = buffer;
/*drop the space*/
while (isspace(*tmp))
{
tmp++;
}
/*cut out the device name from the buffer*/
dev_name = strsep(&tmp, ":");
NET_DBG("dev_name is:%s\n", dev_name);
strncpy(ifr_names[i - 2].dev_name, dev_name, strlen(dev_name));
ifr_names[i - 2].used = true;
}
fclose(fp);
*dev_nums = i - 2;
ERROR0:
return ret;
}
int get_ifconfig(struct ifreq *ifrs, unsigned int input_len, int *ifreq_nums)
{
int sockfd;
struct ifconf ifc;
int count = 0;
int ret = SUCCESS;
if (!ifrs || input_len < (IF_DEV_NUM_MAX * sizeof(struct ifreq)) || !ifreq_nums)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
ifc.ifc_len = input_len;
ifc.ifc_buf = (char *)ifrs;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
{
NET_DBG("ioctl SIOCGIFCONF error\n");
ret = ERR_IOCTL;
goto ERROR1;
}
count = ifc.ifc_len / sizeof(struct ifreq);
*ifreq_nums = count;
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int get_if_ip_addr(char *dev_name, char *ip_address)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !ip_address)
{
NET_ERR("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
memset(ip_address, 0, INET_ADDRSTRLEN);
if (!inet_ntop(AF_INET, &(((struct sockaddr_in *) & (ifr.ifr_addr))->sin_addr),
ip_address, INET_ADDRSTRLEN))
{
NET_ERR("%s: change sockaddr_in to ip_address failed\n", __func__);
ret = ERR_UNKNOWN;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int set_if_ip_addr(char *dev_name, char *ip_address)
{
int sockfd;
int ret = SUCCESS;
struct ifreq ifr;
struct sockaddr_in addr;
if (!dev_name || !ip_address)
{
NET_ERR("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, ip_address, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input ip_address is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the ip_address to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(ifr.ifr_addr), &addr, sizeof(struct sockaddr_in));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int get_if_brd_addr(char *dev_name, char *brd_address)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !brd_address)
{
NET_ERR("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCGIFBRDADDR, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
memset(brd_address, 0, INET_ADDRSTRLEN);
if (!inet_ntop(AF_INET, &(((struct sockaddr_in *) & (ifr.ifr_addr))->sin_addr),
brd_address, INET_ADDRSTRLEN))
{
NET_ERR("%s: change sockaddr_in to brd_address failed\n", __func__);
ret = ERR_UNKNOWN;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int set_if_brd_addr(char *dev_name, char *brd_address)
{
int sockfd;
int ret = SUCCESS;
struct ifreq ifr;
struct sockaddr_in addr;
if (!dev_name || !brd_address)
{
NET_ERR("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, brd_address, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input brd_address is not valied\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the brd_address to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(ifr.ifr_addr), &addr, sizeof(struct sockaddr_in));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCSIFBRDADDR, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int get_if_netmask_addr(char *dev_name, char *netmask_address)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !netmask_address)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCGIFNETMASK, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
memset(netmask_address, 0, INET_ADDRSTRLEN);
if (!inet_ntop(AF_INET, &(((struct sockaddr_in *) & (ifr.ifr_addr))->sin_addr),
netmask_address, INET_ADDRSTRLEN))
{
NET_ERR("%s: change sockaddr_in to netmask_address failed\n", __func__);
ret = ERR_UNKNOWN;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int set_if_netmask_addr(char *dev_name, char *netmask_address)
{
int sockfd;
int ret = SUCCESS;
struct ifreq ifr;
struct sockaddr_in addr;
if (!dev_name || !netmask_address)
{
NET_ERR("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, netmask_address, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input netmask_address is not valied\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the netmask_address to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(ifr.ifr_addr), &addr, sizeof(struct sockaddr_in));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int get_if_mac_addr(char *dev_name, unsigned char *mac_address, unsigned int input_len)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !mac_address || input_len < ETH_ALEN)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
memcpy(mac_address, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int set_if_mac_addr(char *dev_name, unsigned char *mac_address)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !mac_address)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
/*get the device flags first*/
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
/*if the device is up, down it first*/
if (ifr.ifr_flags & IFF_UP)
{
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
}
ifr.ifr_addr.sa_family = ARPHRD_ETHER;
memcpy(ifr.ifr_hwaddr.sa_data, mac_address, ETH_ALEN);
if (ioctl(sockfd, SIOCSIFHWADDR, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int get_if_flags(char *dev_name, short int *if_flags)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !if_flags)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
*if_flags = ifr.ifr_flags;
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int set_if_flags(char *dev_name, short int if_flags)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
ifr.ifr_flags = if_flags;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int get_if_mtu(char *dev_name, int *if_mtu)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !if_mtu)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCGIFMTU, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
*if_mtu = ifr.ifr_mtu;
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int set_if_mtu(char *dev_name, int if_mtu)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
NET_DBG("the device name is %s\n", ifr.ifr_name);
if (if_mtu != -1)
{
ifr.ifr_mtu = if_mtu;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int change_if_name(char *old_dev_name, char *new_dev_name)
{
int sockfd;
struct ifreq ifr;
int ret = SUCCESS;
if (!old_dev_name || !old_dev_name)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, old_dev_name, IFNAMSIZ - 1);
NET_DBG("the old_dev_name is %s\n", ifr.ifr_name);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
/*get the device flags first*/
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
/*if the device is up, down it first*/
if (ifr.ifr_flags & IFF_UP)
{
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
}
strncpy(ifr.ifr_newname, new_dev_name, IFNAMSIZ - 1);
NET_DBG("the new_dev_name is %s\n", ifr.ifr_name);
if (ioctl(sockfd, SIOCSIFNAME, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
/**
*********************
* The APIs of route *
*********************
*/
int get_route_table(libnet_rtentry_t *route_tables, unsigned int input_len, int *rt_table_nums)
{
FILE *fp;
char buffer[1024] = {0};
int num = 0;
char dev_name[16] = {0};
char dst[128] = {0};
struct sockaddr dst_addr;
char gateway[128] = {0};
struct sockaddr gateway_addr;
char netmask[128] = {0};
struct sockaddr netmask_addr;
int iflags, metric, refcnt, use, mss, window, irtt;
int ret = SUCCESS;
int i = 0;
if (!route_tables ||
input_len < (ROUTE_TABLE_NUM_MAX * sizeof(libnet_rtentry_t)) ||
!rt_table_nums)
{
NET_DBG("%s: Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
fp = fopen(ROUTE_TABLE_DEV_NAME, "r");
if (!fp)
{
NET_DBG("%s: open the net device failed\n", __func__);
ret = ERR_NOTEXIST;
goto ERROR0;
}
for (i = 0; fgets(buffer, 1024, fp); ++i)
{
NET_DBG("the buffer is %s\n", buffer);
/*drop the first line*/
if (i < 1)
{
continue;
}
num = sscanf(buffer, "%16s\t%128s\t%128s\t%X\t%d\t%d\t%d\t%128s\t%d\t%d\t%d\t",
dev_name, dst, gateway, &iflags, &refcnt, &use, &metric, netmask,
&mss, &window, &irtt);
if (num < 10 || !(iflags & RTF_UP))
{
continue;
}
NET_DBG("dev_name is:%s\n", dev_name);
strncpy(route_tables[i - 1].dev_name, dev_name, strlen(dev_name));
route_tables[i - 1].used = true;
route_tables[i - 1].route.rt_dev = route_tables[i - 1].dev_name;
change_char_to_sockaddr(dst, &dst_addr);
memcpy(&(route_tables[i - 1].route.rt_dst), &dst_addr, sizeof(struct sockaddr));
change_char_to_sockaddr(gateway, &gateway_addr);
memcpy(&(route_tables[i - 1].route.rt_gateway), &gateway_addr, sizeof(struct sockaddr));
change_char_to_sockaddr(netmask, &netmask_addr);
memcpy(&(route_tables[i - 1].route.rt_genmask), &netmask_addr, sizeof(struct sockaddr));
route_tables[i - 1].route.rt_flags = iflags;
NET_DBG("%x\n", route_tables[i - 1].route.rt_flags);
}
fclose(fp);
*rt_table_nums = i - 1;
ERROR0:
return ret;
}
int add_route_rule(char *dst_type, char *dst_addr, char *netmask_addr, char *gw_addr,
char *dev_name)
{
int sockfd;
int ret = SUCCESS;
struct rtentry route;
struct sockaddr_in addr;
if (!dst_addr || !(dev_name || gw_addr))
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&route, 0, sizeof(struct rtentry));
/*the route rule is net*/
if (!strncmp("net", dst_type, 3))
{
if (!netmask_addr)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
route.rt_flags = RTF_UP;
}
/*the route rule is host*/
if (!strncmp("host", dst_type, 4))
{
route.rt_flags = RTF_UP | RTF_HOST;
}
/*dst address setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, dst_addr, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input dst_addr is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the dst_addr to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(route.rt_dst), &addr, sizeof(struct sockaddr_in));
/*net mask setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, netmask_addr, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input netmask_addr is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the netmask_addr to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(route.rt_genmask), &addr, sizeof(struct sockaddr_in));
/*device setting*/
if (dev_name)
{
route.rt_dev = dev_name;
}
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
if (gw_addr && strncmp(gw_addr, "0.0.0.0", strlen("0.0.0.0")))
{
route.rt_flags = RTF_UP | RTF_GATEWAY;
/*gw address setting*/
ret = inet_pton(AF_INET, gw_addr, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input gw_addr is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the gw_addr to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
}
else
{
addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
memcpy(&(route.rt_gateway), &addr, sizeof(struct sockaddr_in));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCADDRT, &route) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int del_route_rule(char *dst_type, char *dst_addr, char *netmask_addr, char *gw_addr,
char *dev_name)
{
int sockfd;
int ret = SUCCESS;
struct rtentry route;
struct sockaddr_in addr;
if (!dst_addr || !netmask_addr)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&route, 0, sizeof(struct rtentry));
/*the route rule is net*/
if (!strncmp("net", dst_type, 3))
{
route.rt_flags = RTF_UP;
}
/*the route rule is host*/
if (!strncmp("host", dst_type, 4))
{
route.rt_flags = RTF_UP | RTF_HOST;
}
/*dst address setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, dst_addr, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input dst_addr is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the dst_addr to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(route.rt_dst), &addr, sizeof(struct sockaddr_in));
/*net mask setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, netmask_addr, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input netmask_addr is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the netmask_addr to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(route.rt_genmask), &addr, sizeof(struct sockaddr_in));
/*device setting*/
if (dev_name)
{
route.rt_dev = dev_name;
}
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
if (gw_addr && strncmp(gw_addr, "0.0.0.0", strlen("0.0.0.0")))
{
route.rt_flags = RTF_UP | RTF_GATEWAY;
/*gw address setting*/
ret = inet_pton(AF_INET, gw_addr, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input gw_addr is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the gw_addr to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
}
else
{
addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
memcpy(&(route.rt_gateway), &addr, sizeof(struct sockaddr_in));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCDELRT, &route) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int add_route_rule_def_gw(char *def_gw, char *dev_name)
{
int sockfd;
int ret = SUCCESS;
struct rtentry route;
struct sockaddr_in addr;
if (!def_gw)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&route, 0, sizeof(struct rtentry));
/*dst address setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
memcpy(&(route.rt_dst), &addr, sizeof(struct sockaddr_in));
/*net mask setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
memcpy(&(route.rt_genmask), &addr, sizeof(struct sockaddr_in));
/*device setting*/
if (dev_name)
{
route.rt_dev = dev_name;
}
route.rt_flags = RTF_UP | RTF_GATEWAY;
/*gw address setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, def_gw, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input def_gw is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the def_gw to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(route.rt_gateway), &addr, sizeof(struct sockaddr_in));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCADDRT, &route) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int del_route_rule_def_gw(char *def_gw, char *dev_name)
{
int sockfd;
int ret = SUCCESS;
struct rtentry route;
struct sockaddr_in addr;
if (!def_gw)
{
NET_ERR("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&route, 0, sizeof(struct rtentry));
/*dst address setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
memcpy(&(route.rt_dst), &addr, sizeof(struct sockaddr_in));
/*net mask setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
memcpy(&(route.rt_genmask), &addr, sizeof(struct sockaddr_in));
/*dev_name settings*/
if (dev_name)
{
route.rt_dev = dev_name;
}
route.rt_flags = RTF_UP | RTF_GATEWAY;
/*gw address setting*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
ret = inet_pton(AF_INET, def_gw, &(addr.sin_addr));
if (0 == ret)
{
NET_ERR("%s: the input def_gw is Invalided\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
else if (-1 == ret)
{
NET_ERR("%s: change the def_gw to sockaddr_in failed\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memcpy(&(route.rt_gateway), &addr, sizeof(struct sockaddr_in));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCADDRT, &route) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
/**
***********************
*The APIs of ethtool *
***********************
*/
int get_ethtool_ecmd(char *dev_name, uint32_t *speed, uint8_t *duplex, uint8_t *autoneg,
uint32_t *supported, uint32_t *advertising)
{
int sockfd;
struct ethtool_cmd ecmd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !speed || !duplex || !autoneg || !supported || !advertising)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
ecmd.cmd = ETHTOOL_GSET;
ifr.ifr_data = (caddr_t)&ecmd;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
*speed = ethtool_cmd_speed(&ecmd);
*duplex = ecmd.duplex;
*autoneg = ecmd.autoneg;
*supported = ecmd.supported;
*advertising = ecmd.advertising;
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int set_ethtool_ecmd(char *dev_name, uint32_t speed, uint8_t duplex, uint8_t autoneg)
{
int sockfd;
struct ethtool_cmd ecmd;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
ecmd.cmd = ETHTOOL_GSET;
ifr.ifr_data = (caddr_t)&ecmd;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
NET_ERR("%s: create sockfd failed. errno: %s", __func__, strerror(errno));
ret = ERR_UNKNOWN;
goto ERROR0;
}
if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
else
{
ethtool_cmd_speed_set(&ecmd, speed);
ecmd.duplex = duplex;
ecmd.autoneg = autoneg;
if (ecmd.autoneg && ecmd.advertising == 0)
{
NET_DBG("Cannot advertise");
NET_DBG("speed %d\n", speed);
NET_DBG("duplex %s\n", duplex ? "full" : "half");
ret = ERR_WRONGVALS;
goto ERROR1;
}
ecmd.cmd = ETHTOOL_SSET;
ifr.ifr_data = (caddr_t)&ecmd;
if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
}
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
int get_ethtool_link(char *dev_name, uint32_t *eth_data)
{
int sockfd;
struct ethtool_value edata;
struct ifreq ifr;
int ret = SUCCESS;
if (!dev_name || !eth_data)
{
NET_DBG("%s:Invalid input parameter\n", __func__);
ret = ERR_WRONGVALS;
goto ERROR0;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
edata.cmd = ETHTOOL_GLINK;
ifr.ifr_data = (caddr_t)&edata;
if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0)
{
NET_ERR("%s: ioctl error errno:%s\n", __func__, strerror(errno));
ret = ERR_IOCTL;
goto ERROR1;
}
*eth_data = edata.data;
ERROR1:
close(sockfd);
ERROR0:
return ret;
}
/**
*****************************************
*The APIs of to monitor network status *
*****************************************
*/
void parse_rtattr(struct rtattr **tb, int max, struct rtattr *attr, int len)
{
for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
{
if (attr->rta_type <= max)
{
tb[attr->rta_type] = attr;
}
}
}
void print_ifinfomsg(struct nlmsghdr *nh)
{
int len;
struct rtattr *tb[IFLA_MAX + 1];
struct ifinfomsg *ifinfo;
memset(tb, 0, sizeof(tb));
ifinfo = (struct ifinfomsg *)NLMSG_DATA(nh);
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifinfo), len);
NET_DBG("%s: %s ", (nh->nlmsg_type == RTM_NEWLINK) ? "NEWLINK" : "DELLINK",
(ifinfo->ifi_flags & IFF_RUNNING) ? "up" : "down");
if (tb[IFLA_IFNAME])
{
NET_ERR("%s", (char *)RTA_DATA(tb[IFLA_IFNAME]));
}
NET_DBG("\n");
}
void print_ifaddrmsg(struct nlmsghdr *nh)
{
int len;
struct rtattr *tb[IFA_MAX + 1];
struct ifaddrmsg *ifaddr;
char tmp[256];
memset(tb, 0, sizeof(tb));
ifaddr = (struct ifaddrmsg *)NLMSG_DATA(nh);
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifaddr));
parse_rtattr(tb, IFA_MAX, IFA_RTA(ifaddr), len);
NET_DBG("%s ", (nh->nlmsg_type == RTM_NEWADDR) ? "NEWADDR" : "DELADDR");
if (tb[IFA_LABEL] != NULL)
{
NET_DBG("%s ", (char *)RTA_DATA(tb[IFA_LABEL]));
}
if (tb[IFA_ADDRESS] != NULL)
{
inet_ntop(ifaddr->ifa_family, RTA_DATA(tb[IFA_ADDRESS]), tmp, sizeof(tmp));
NET_DBG("%s ", tmp);
}
NET_DBG("\n");
}
void print_rtmsg(struct nlmsghdr *nh)
{
int len;
struct rtattr *tb[RTA_MAX + 1];
struct rtmsg *rt;
char tmp[256];
memset(tb, 0, sizeof(tb));
rt = (struct rtmsg *)NLMSG_DATA(nh);
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*rt));
parse_rtattr(tb, RTA_MAX, RTM_RTA(rt), len);
NET_DBG("%s: ", (nh->nlmsg_type == RTM_NEWROUTE) ? "NEWROUT" : "DELROUT");
if (tb[RTA_DST] != NULL)
{
inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_DST]), tmp, sizeof(tmp));
NET_DBG("RTA_DST %s ", tmp);
}
if (tb[RTA_SRC] != NULL)
{
inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_SRC]), tmp, sizeof(tmp));
NET_DBG("RTA_SRC %s ", tmp);
}
if (tb[RTA_GATEWAY] != NULL)
{
inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_GATEWAY]), tmp, sizeof(tmp));
NET_DBG("RTA_GATEWAY %s ", tmp);
}
NET_DBG("\n");
}
int monitor_network_status(ifinfo_msg_fp ifinfomsg_cb, ifaddr_msg_fp ifaddrmsg_cb,
rt_msg_fp rtmsg_cb)
{
int socketfd;
struct sockaddr_nl sa;
struct timeval timeout;
fd_set rd_set;
int select_r;
unsigned int read_r;
struct nlmsghdr *nh;
char buffer[2048] = {0};
int ret = SUCCESS;
socketfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (socketfd < 0)
{
NET_ERR("%s: create socketfd failed\n", __func__);
ret = ERR_UNKNOWN;
goto ERROR0;
}
memset(&sa, 0, sizeof(struct sockaddr_nl));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
ret = bind(socketfd, (struct sockaddr *)&sa, sizeof(struct sockaddr));
if (ret == -1)
{
NET_ERR("%s: bind socketfd failed\n", __func__);
ret = ERR_UNKNOWN;
goto ERROR1;
}
while (true)
{
FD_ZERO(&rd_set);
FD_SET(socketfd, &rd_set);
timeout.tv_sec = 15;
timeout.tv_usec = 0;
select_r = select(socketfd + 1, &rd_set, NULL, NULL, &timeout);
if (select_r < 0)
{
NET_ERR("%s: select error\n", __func__);
}
else if (select_r > 0)
{
if (FD_ISSET(socketfd, &rd_set))
{
read_r = read(socketfd, buffer, 2048);
for (nh = (struct nlmsghdr *)buffer; NLMSG_OK(nh, read_r); nh = NLMSG_NEXT(nh, read_r))
{
switch (nh->nlmsg_type)
{
case NLMSG_DONE:
case NLMSG_ERROR:
break;
case RTM_NEWLINK:
case RTM_DELLINK:
ifinfomsg_cb(nh);
break;
case RTM_NEWADDR:
case RTM_DELADDR:
ifaddrmsg_cb(nh);
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
rtmsg_cb(nh);
break;
default:
NET_WAR("nh->nlmsg_type = %d\n", nh->nlmsg_type);
break;
}
}
}
}
}
ERROR1:
close(socketfd);
ERROR0:
return ret;
}
net_network.h
#ifndef __libnetwork_h__
#define __libnetwork_h__
#include <net/route.h>
#include <linux/rtnetlink.h>
#define NET_DEV_NAME "/proc/net/dev"
#define ROUTE_TABLE_DEV_NAME "/proc/net/route"
#define DEVICE_NAME_MAX 16
#define IF_DEV_NUM_MAX 128
#define ROUTE_TABLE_NUM_MAX 128
#define DESTINATION_TYPE_MAX 8
/*the struct to store the device name*/
typedef struct
{
char dev_name[DEVICE_NAME_MAX];
bool used;
} ifr_name_t;
/*the struct to store the route table*/
typedef struct
{
char dev_name[DEVICE_NAME_MAX];
bool used;
struct rtentry route;
} libnet_rtentry_t;
typedef int (*ifinfo_msg_fp)(struct nlmsghdr *);
typedef int (*ifaddr_msg_fp)(struct nlmsghdr *);
typedef int (*rt_msg_fp)(struct nlmsghdr *);
#ifndef SUCCESS
#define SUCCESS (0)
#endif
#ifndef ERR_UNKNOWN
#define ERR_UNKNOWN (-1) /* Unknown error */
#endif
#ifndef ERR_WRONGVALS
#define ERR_WRONGVALS (-2) /* Wrong input arguments or return values */
#endif
#ifndef ERR_NOMEM
#define ERR_NOMEM (-3) /* Out of memory */
#endif
#ifndef ERR_WRONGSTATE
#define ERR_WRONGSTATE (-4) /* Wrong running state */
#endif
#ifndef ERR_EXIST
#define ERR_EXIST (-5) /* Target already exists */
#endif
#ifndef ERR_NOTEXIST
#define ERR_NOTEXIST (-6) /* Target not exist yet */
#endif
#ifndef ERR_NOBUFS
#define ERR_NOBUFS (-7) /* No buffer space left */
#endif
#ifndef ERR_NODATA
#define ERR_NODATA (-8) /* No data available or the buffer is empty */
#endif
#ifndef ERR_NOTIMPL
#define ERR_NOTIMPL (-9) /* Function not implemented yet */
#endif
#ifndef ERR_TIMEDOUT
#define ERR_TIMEDOUT (-10) /* Waiting resource timed out */
#endif
#ifndef ERR_NOSWRSRC
#define ERR_NOSWRSRC (-11) /* No software resource */
#endif
#ifndef ERR_NOHWRSRC
#define ERR_NOHWRSRC (-12) /* No hardware resource */
#endif
#ifndef ERR_IOCTL
#define ERR_IOCTL (-13) /*ioctl error*/
#endif
/**
************************
* The APIs of ifconfig *
************************
*/
/**
*get the net device name from the /proc/net/dev
*@param ifr_names -out- the buffer to store the device name.
*@param input_len -in- the buffer size of ifr_names should be MAX_IF_DEV_NUM * sizeof(ifr_name_t)
*@param dev_num -out- the numbers of get device number
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_if_dev_name(ifr_name_t *ifr_names, unsigned int input_len, int *dev_nums);
/**
*get the active ifreqs
*@param ifrs -out- the buffer store the ifreqs
*@param input_len -in- the buffer size of ifr_names should be MAX_IF_DEV_NUM * sizeof(struct ifreq)
*@param ifreq_nums -out- the num of the active ifreqs
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_ifconfig(struct ifreq *ifrs, unsigned int input_len, int *ifreq_nums);
/**
*get the ip address of specific device by name
*@param dev_name -in- the device name point
*@param address -out- the buffer to store ip address like "xxx.xxx.xxx.xxx"
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_if_ip_addr(char *dev_name, char *ip_address);
/**
*set the ip address of specific device by name
*@param dev_name -in- the device name point
*@param address -in- the buffer to store ip address like "xxx.xxx.xxx.xxx"
*@return SUCCESS - set successfully
*@return ERR_xxx - failed to set
*/
int set_if_ip_addr(char *dev_name, char *ip_address);
/**
*get the broadcast address of specific device by name
*@param dev_name -in- the device name point
*@param brd_address -out- the buffer to store broadcast address like "xxx.xxx.xxx.xxx"
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_if_brd_addr(char *dev_name, char *brd_address);
/**
*set the broadcast address of specific device by name
*@param dev_name -in- the device name point
*@param brd_address -in- the buffer to store broadcast address like "xxx.xxx.xxx.xxx"
*@return SUCCESS - set successfully
*@return ERR_xxx - failed to set
*/
int set_if_brd_addr(char *dev_name, char *brd_address);
/**
*get the netmask address of specific device by name
*@param dev_name -in- the device name point
*@param address -out- the buffer to store netmask address like "xxx.xxx.xxx.xxx"
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_if_netmask_addr(char *dev_name, char *netmask_address);
/**
*set the netmask address of specific device by name
*@param dev_name -in- the device name point
*@param address -in- the buffer to store netmask address like "xxx.xxx.xxx.xxx"
*@return SUCCESS - set successfully
*@return ERR_xxx - failed to set
*/
int set_if_netmask_addr(char *dev_name, char *netmask_address);
/**
*get the if flags of specific device by name
*@param dev_name -in- the device name point
*@param if_flags -out- the buffer to store if_flags
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_if_flags(char *dev_name, short int *if_flags);
/**
*get the if flags of specific device by name
*@param dev_name -in- the device name point
*@param if_flags -in- the buffer to store if_flags
*@return SUCCESS - set successfully
*@return ERR_xxx - failed to set
*/
int set_if_flags(char *dev_name, short int if_flags);
/**
*get the mac address of specific device by name
*@param dev_name -in- the device name point
*@param mac_addr -out- the buffer to store mac address like
*@param input_len -in- the length of mac_addr
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_if_mac_addr(char *dev_name, unsigned char *mac_address, unsigned int input_len);
/**
*set the mac address of specific device by name
*@param dev_name -in- the device name point
*@param mac_addr -in- the buffer to store mac address
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int set_if_mac_addr(char *dev_name, unsigned char *mac_address);
/**
*get the mac address of specific device by name
*@param dev_name -in- the device name point
*@param if_mtu -out- the buffer to store if_mtu
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_if_mtu(char *dev_name, int *if_mtu);
/**
*set the if_mtu of specific device by name
*@param dev_name -in- the device name point
*@param if_mtu -in- the buffer to store if_mtu
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int set_if_mtu(char *dev_name, int if_mtu);
/**
*change the device name
*@param old_dev_name -in- the old device name point
*@param new_dev_name -in- the new device name point
*@return SUCCESS - change successfully
*@return ERR_xxx - failed to change
*/
int change_if_name(char *old_dev_name, char *new_dev_name);
/**
*********************
* The APIs of route *
*********************
*/
/**
*get the route tables from the /proc/net/route
*@param route_tables -in- the buffer to store the route tables
*@param input_len -in- the buffer len of route_tables should
*be MAX_ROUTE_TABLE_NUM * sizeof(libnet_rtentry_t)
*@param rt_table_nums -out- the buffer to store the route rule numbers
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_route_table(libnet_rtentry_t *route_tables, unsigned int input_len, int *rt_table_nums);
/**
*add the net route rule
*@param dst_type -in- the buffer to store the route rule type like "net" or "host"
*@param dst_addr -in- the buffer to store the destination address like "xxx.xxx.xxx.xxx"
*@param net_mask -in- the buffer to store the netmask address like "xxx.xxx.xxx.xxx"
*@param gw_addr -in- the buffer to store the gateway address like "xxx.xxx.xxx.xxx" or NULL
*@param dev_name -in- the buffer to store the device name
*@return SUCCESS - add_route_rule_net successfully
*@return ERR_xxx - failed to add_route_rule_net
*/
int add_route_rule(char *dst_type, char *dst_addr, char *net_mask, char *gw_addr, char *dev_name);
/**
*del the net route rule
*@param dst_type -in- the buffer to store the route rule type like "net" or "host"
*@param dst_addr -in- the buffer to store the destination address like "xxx.xxx.xxx.xxx"
*@param net_mask -in- the buffer to store the netmask address like "xxx.xxx.xxx.xxx"
*@param gw_addr -in- the buffer to store the gateway address like "xxx.xxx.xxx.xxx" or NULL
*@param dev_name -in- the buffer to store the device name
*@return SUCCESS - del_route_rule_net successfully
*@return ERR_xxx - failed to del_route_rule_net
*/
int del_route_rule(char *dst_type, char *dst_addr, char *net_mask, char *gw_addr, char *dev_name);
/**
*add the defult gateway route rule
*@param dst_addr -in- the buffer to store the default gateway address like "xxx.xxx.xxx.xxx"
*@param dev_name -in- the buffer to store the device name, you can ignore it by set it as NULL
*@return SUCCESS - add_route_rule_def_gw successfully
*@return ERR_xxx - failed to add_route_rule_def_gw
*/
int add_route_rule_def_gw(char *def_gw, char *dev_name);
/**
*del the defult gateway route rule
*@param dst_addr -in- the buffer to store the default gateway address like "xxx.xxx.xxx.xxx"
*@param dev_name -in- the buffer to store the device name, you can ignore it by set it as NULL
*@return SUCCESS - del_route_rule_def_gw successfully
*@return ERR_xxx - failed to del_route_rule_def_gw
*/
int del_route_rule_def_gw(char *def_gw, char *dev_name);
/**
***********************
*The APIs of ethtool *
***********************
*/
/**
*get the ethtool cmd data
*@param dev_name -in- the buffer to store the device name
*@param speed -out- the buffer to store the speed
*@param duplex -out- the buffer to store the duplex
*@param autoneg -out- the buffer to store the autoneg
*@param supported -out- the buffer to store the supported
*@param advertising -out- the buffer to store the advertising
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_ethtool_ecmd(char *dev_name, uint32_t *speed, uint8_t *duplex, uint8_t *autoneg,
uint32_t *supported, uint32_t *advertising);
/**
*get the ethtool cmd data
*@param dev_name -in- the buffer to store the device name
*@param speed -in- the buffer to store the speed
*@param duplex -in- the buffer to store the duplex
*@param autoneg -in- the buffer to store the autoneg
*@return SUCCESS - set successfully
*@return ERR_xxx - failed to set
*/
int set_ethtool_ecmd(char *dev_name, uint32_t speed, uint8_t duplex, uint8_t autoneg);
/**
*del the defult gateway route rule
*@param dev_name -in- the buffer to store the device name
*@param eth_data -out- the buffer to store the eth_data 0 means no connected; 1 means connected
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int get_ethtool_link(char *dev_name, uint32_t *eth_data);
void parse_rtattr(struct rtattr **tb, int max, struct rtattr *attr, int len);
/**
*del the defult gateway route rule
*@param ifinfomsg_cb -in- the call back funtion to handle the ifinfo message
*@param ifaddrmsg_cb -in- the call back funtion to handle the ifaddr message
*@param rtmsg_cb -in- the call back funtion to handle the route table message
*@return SUCCESS - get successfully
*@return ERR_xxx - failed to get
*/
int monitor_network_status(ifinfo_msg_fp ifinfomsg_cb, ifaddr_msg_fp ifaddrmsg_cb,
rt_msg_fp rtmsg_cb);
#endif /* #ifndef __error_codes_h__ */