LInux环境下以太网的查询修改等操作(C实现)
2024-01-18 本文已影响0人
狼少丷
一、每个方法的实现
0. 0 宏和一些声明
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if_arp.h>
#include <linux/nl80211.h>
#include <linux/wireless.h>
#include <netinet/if_ether.h>
#include "HRDSP.h"
static struct ifreq ifr;
static int fd;
0.1 创建套接字Socket
/* 创建Socket */
static int if_socket()
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
perror("socket");
return FALSE;
}
return sock;
}
1. 检测指定网络接口是否存在
bool_t netif_is_exist(const char *ifname)
{
// 创建socket以进行ioctl调用
fd = if_socket();
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
else
return TRUE;
}
2. 检测指定网络接口链路是否连接
bool_t netif_is_link(const char *ifname)
{
// 创建socket以进行ioctl调用
fd = if_socket();
// 清零ifr结构体并设置要检查的接口名称
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
// 调用ioctl获取网络接口标志
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
{
perror("ioctl");
close(fd);
exit(1);
}
// 检查IFF_RUNNING标志,确定链路状态
if (ifr.ifr_flags & IFF_RUNNING)
{
return TRUE;
}
else
{
return FALSE;
}
// 关闭socket
close(fd);
}
3. 检测指定网络接口是否开启
bool_t netif_is_up(const char *ifname)
{
// 创建socket以进行ioctl调用
fd = if_socket();
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
if (ifr.ifr_flags & IFF_UP)
{
return TRUE;
}
else
{
return FALSE;
}
}
4. 开启或关闭网络接口
bool_t netif_up(const char *ifname, bool_t up)
{
// 创建socket以进行ioctl操作
fd = if_socket();
// 清零ifr结构体,并设置需要操作的网络接口名
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
// 获取当前网络接口的配置
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
perror("SIOCGIFFLAGS");
close(fd);
return FALSE;
}
if (netif_is_up(ifname) == up)
{
// 当前状态与需求状态一致
return TRUE;
}
else
{
// 根据enable的值设置IFF_UP标志位来打开或关闭网络接口
if (up == TRUE)
{
ifr.ifr_flags |= IFF_UP;
}
else
{
ifr.ifr_flags &= ~IFF_UP;
}
// 设置网络接口的状态
if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
{
perror("SIOCSIFFLAGS");
close(fd);
return FALSE;
}
}
close(fd);
// 检查开启转态并返回
return netif_is_up(ifname) == up;
}
5.获取指定网络接口MAC地址
bool_t netif_get_mac(const char *ifname, MacAddr_t mac)
{
// 创建socket以进行ioctl调用
fd = if_socket();
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
return TRUE;
}
6. 设置指定网络接口MAC地址
bool_t netif_set_mac(const char *ifname, MacAddr_t mac)
{
// 创建socket以进行ioctl调用
fd = if_socket();
// 指定要修改的网络接口
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
// 准备好新的MAC地址
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
memcpy(ifr.ifr_hwaddr.sa_data, mac, ETH_ALEN);
// 调用ioctl设置MAC地址
if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
return TRUE;
}
7. 获取指定网络接口IP地址
bool_t netif_get_ip(const char *ifname, in_addr_t *ip)
{
// 创建socket以进行ioctl调用
fd = if_socket();
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFADDR, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
*ip = addr->sin_addr.s_addr;
return TRUE;
}
8. 设置指定网络接口IP地址
bool_t netif_set_ip(const char *ifname, const char *in_addr_tip)
{
// 构建设置IP地址的命令字符串
char command[100];
snprintf(command, sizeof(command), "ifconfig %s %s", ifname, in_addr_tip);
// 执行命令,设置IP地址
int ret = system(command);
if (ret == -1)
{
printf("Failed to set IP address.\n");
return FALSE;
}
else
{
printf("IP address set successfully.\n");
return TRUE;
}
}
9.获取指定网络接口子网掩码
bool_t netif_get_mask(const char *ifname, in_addr_t *ip)
{
// 创建socket以进行ioctl调用
fd = if_socket();
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_netmask;
*ip = addr->sin_addr.s_addr;
return TRUE;
}
10. 设置指定网络接口子网掩码
bool_t netif_set_mask(const char *ifname, in_addr_t mask)
{
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
struct sockaddr_in *addr;
// 创建socket以进行ioctl调用
fd = if_socket();
// 清空ifr结构体并设置网络接口名称,例如 "eth0"
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
// 获取当前的子网掩码
if (ioctl(fd, SIOCGIFNETMASK, &ifr) == -1)
{
perror("ioctl");
close(fd);
exit(EXIT_FAILURE);
}
// 准备好 sockaddr_in 结构体设置子网掩码
addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = mask;
// 使用SIOCSIFNETMASK ioctl命令设置子网掩码
if (ioctl(fd, SIOCSIFNETMASK, &ifr) == -1)
{
perror("ioctl SIOCSIFNETMASK failed");
close(fd);
return FALSE;
}
// 操作成功
close(fd);
return TRUE;
}
11.设置指定网络接口发送队列长度
bool_t netif_set_txqueue(const char *ifname, uint32_t len)
{
// 构建设置IP地址的命令字符串
char command[100];
snprintf(command, sizeof(command), "ifconfig %s txqueuelen %d", ifname, len);
// 执行命令,设置IP地址
int ret = system(command);
if (ret == -1)
{
printf("Failed to set txqueuelen.\n");
return FALSE;
}
else
{
printf("TxqueueLen set successfully.\n");
return TRUE;
}
}
12. 设置指定网络接口最大包负载MTU
bool_t netif_set_mtu(const char *ifname, uint32_t mtu)
{
// 为了设置MTU先关不端口
if (netif_up(ifname, 0) != TRUE)
{
return FALSE;
}
// 创建socket以进行ioctl调用
fd = if_socket();
// 清零结构体
memset(&ifr, 0, sizeof(ifr));
// 指定网络接口名称
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
// 获取当前接口参数
if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
{
perror("0 ioctl SIOCGIFMTU");
close(fd);
return FALSE;
}
printf("Current MTU of %s is %d chenge %d\n", ifname, ifr.ifr_mtu, mtu);
if (ifr.ifr_mtu == mtu)
{
printf("Current MTU of %s is %d == %d\n", ifname, ifr.ifr_mtu, mtu);
return TRUE;
}
// 设置新的MTU
ifr.ifr_mtu = mtu;
if (ioctl(fd, SIOCSIFMTU, &ifr) != 0)
{
perror("ioctl");
return FALSE;
}
// 再次获取新设置的MTU
if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
printf("New MTU of %s is %d\n", ifname, ifr.ifr_mtu);
// 关闭socket
close(fd);
// 设置MTU后再重启端口
netif_up(ifname, 1);
return TRUE;
}
13.获取收发包的数量
bool_t netif_get_bytes(char *ifname, unsigned long long *tx_bytes, unsigned long long *rx_bytes)
{
FILE *fp;
char buffer[1024];
char *line;
// 打开/proc/net/dev文件
fp = fopen("/proc/net/dev", "r");
if (fp == NULL)
{
perror("Error opening file");
return FALSE;
}
// 读取文件,直到找到相应的网络接口
while (fgets(buffer, sizeof(buffer), fp))
{
if (strstr(buffer, ifname))
{
// 这里假设行的格式是以下这种类型的:
// eth0: 123455 162100 ...(其他统计数据)
// 您可能需要根据实际情况调整 sscanf 的格式字符串来适配
// 解析接收和发送的数据包数量
line = strstr(buffer, ifname);
sscanf(line, "%*s %lu %*d %*d %*d %*d %*d %*d %*d %lu", rx_bytes, tx_bytes);
printf("Interface: %s\n", ifname);
break;
}
}
// 关闭文件
fclose(fp);
return TRUE;
}
14.获取无线是否连接(连接个数)
int wlan_get_count(const char *ifname)
{
char cmd[256];
FILE *fp;
int count = 0;
char buffer[256];
// 创建获取无线设备列表的命令字符串
snprintf(cmd, sizeof(cmd), "iw dev %s station dump | grep Station | wc -l", ifname);
// 打开命令用于读取
if ((fp = popen(cmd, "r")) == NULL)
{
printf("Error opening pipe!\n");
return -1;
}
// 从管道中读取输出
if (fgets(buffer, sizeof(buffer), fp) != NULL)
{
// 将输出字符串转换为整数
count = atoi(buffer);
}
// 关闭管道
if (pclose(fp))
{
printf("Command not found or exited with error status\n");
return -1;
}
return count;
}
15.重新配置生效无线网络参数,当修改完无线网络参数后,可以调用此函数重启端口
int wlan_restart(void)
{
// system("iwconfig wlan0 key s:your_key");
// system("iwconfig wlan0 essid your_essid");
// wlan0 ifname 根据自己的端口来替换
if (netif_is_up("wlan0") == TRUE)
{
// 如果开启就关闭无线接口
int result_down = system("ifconfig wlan0 down");
if (result_down == -1)
{
perror("system");
return FALSE;
}
}
// 重新启动无线接口
int result_up = system("ifconfig wlan0 up");
if (result_up == -1)
{
perror("system");
return FALSE;
}
return TRUE;
}
16.重新配置网络参数,包括Ethernet、WiFi、Bluetooth、LTE等 当修改完网络参数后,可以调用此函数重启此服务
int net_restart(void)
{
int result = system("systemctl restart NetworkManager");
if (result == -1)
{
perror("system");
return FALSE;
}
return TRUE;
}
17.获取无线连接信号强度(dBm)
int wlan_get_signal(const char *ifname)
{
char cmd[1024];
FILE *fp;
char line[256];
int signal_strength = 0;
// 构建iwconfig命令,替换你的无线接口名(比如wlan0)
snprintf(cmd, sizeof(cmd), "iwconfig %s", ifname);
// 执行命令
fp = popen(cmd, "r");
if (fp == NULL)
{
perror("popen");
return EXIT_FAILURE;
}
// 读取命令返回的内容
while (fgets(line, sizeof(line), fp) != NULL)
{
char *ptr;
// 在返回的内容中查找"Signal level"字段
if ((ptr = strstr(line, "Signal level")) != NULL)
{
// 解析信号强度
sscanf(ptr, "Signal level=%d dBm", &signal_strength);
break;
}
}
// 关闭fp指针
pclose(fp);
return signal_strength;
}
二、整体实现代码
2.1 宏定义 HRDSP.h
文件
#ifndef HRDSP_H
#define HRDSP_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <netinet/in.h>
typedef unsigned char MacAddr_t[6]; // MacAddr_t[ETH_ALEN]
typedef enum
{
FALSE,
TRUE
} bool_t;
// 1. 检测指定网络接口是否存在 -----------------------------------
bool_t netif_is_exist(const char *ifname);
// 2. 检测指定网络接口链路是否连接 -----------------------------------
bool_t netif_is_link(const char *ifname);
// 3. 检测指定网络接口是否开启 -----------------------------------
bool_t netif_is_up(const char *ifname);
// 4. 开启或关闭网络接口 0:关闭 、1:开启 -----------------------------------
bool_t netif_up(const char *ifname, bool_t up);
// 5.获取指定网络接口MAC地址 -----------------------------------
bool_t netif_get_mac(const char *ifname, MacAddr_t mac);
// 6. 设置指定网络接口MAC地址 -----------------------------------
bool_t netif_set_mac(const char *ifname, MacAddr_t mac);
// 7. 获取指定网络接口IP地址 -----------------------------------
bool_t netif_get_ip(const char *ifname, in_addr_t *ip);
// 8. 设置指定网络接口IP地址 -----------------------------------
bool_t netif_set_ip(const char *ifname, const char *in_addr_tip);
// 9.获取指定网络接口子网掩码 ---------------------------------
bool_t netif_get_mask(const char *ifname, in_addr_t *ip);
// 10. 设置指定网络接口子网掩码 -----------------------------------
bool_t netif_set_mask(const char *ifname, in_addr_t mask);
// 11.设置指定网络接口发送队列长度 ----------------------------
bool_t netif_set_txqueue(const char *ifname, uint32_t len);
// 12. 设置指定网络接口最大包负载MTU -----------------------------------
bool_t netif_set_mtu(const char *ifname, uint32_t mtu);
// 13.获取收发包的数量 -----------------------------------
bool_t netif_get_bytes(char *ifname, unsigned long long *tx_bytes, unsigned long long *rx_bytes);
// 14.获取无线是否连接(连接个数) -----------------------------------
int wlan_get_count(const char *ifname);
// 15.重新配置生效无线网络参数,当修改完无线网络参数后,可以调用此函数 ---------------
int wlan_restart(void);
// 16.重新配置网络参数,包括Ethernet、WiFi、Bluetooth、LTE等 当修改完网络参数后,可以调用此函数 -----------------------------------
int net_restart(void);
// 17.获取无线连接信号强度(dBm) -----------------------------------
int wlan_get_signal(const char *ifname);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
2.2 核心实现代码 (部分犯法需要sudo
甚至是root
权限,我用的板卡是有sudo
权限的)
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if_arp.h>
#include <linux/nl80211.h>
#include <linux/wireless.h>
#include <netinet/if_ether.h>
#include "HRDSP.h"
static struct ifreq ifr;
static int fd;
/* 创建Socket */
static int if_socket()
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
perror("socket");
return FALSE;
}
return sock;
}
/*1. 检测指定网络接口是否存在 J*/
bool_t netif_is_exist(const char *ifname)
{
// 创建socket以进行ioctl调用
fd = if_socket();
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
else
return TRUE;
}
/*2. 检测指定网络接口链路是否连接 X*/
bool_t netif_is_link(const char *ifname)
{
// 创建socket以进行ioctl调用
fd = if_socket();
// 清零ifr结构体并设置要检查的接口名称
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
// 调用ioctl获取网络接口标志
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
{
perror("ioctl");
close(fd);
exit(1);
}
// 检查IFF_RUNNING标志,确定链路状态
if (ifr.ifr_flags & IFF_RUNNING)
{
return TRUE;
}
else
{
return FALSE;
}
// 关闭socket
close(fd);
}
/*3. 检测指定网络接口是否开启 J*/
bool_t netif_is_up(const char *ifname)
{
// 创建socket以进行ioctl调用
fd = if_socket();
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
if (ifr.ifr_flags & IFF_UP)
{
return TRUE;
}
else
{
return FALSE;
}
}
/*4. 开启或关闭网络接口 0:关闭 、1:开启 X*/
bool_t netif_up(const char *ifname, bool_t up)
{
// 创建socket以进行ioctl操作
fd = if_socket();
// 清零ifr结构体,并设置需要操作的网络接口名
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
// 获取当前网络接口的配置
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
perror("SIOCGIFFLAGS");
close(fd);
return FALSE;
}
if (netif_is_up(ifname) == up)
{
// 当前状态与需求状态一致
return TRUE;
}
else
{
// 根据enable的值设置IFF_UP标志位来打开或关闭网络接口
if (up == TRUE)
{
ifr.ifr_flags |= IFF_UP;
}
else
{
ifr.ifr_flags &= ~IFF_UP;
}
// 设置网络接口的状态
if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
{
perror("SIOCSIFFLAGS");
close(fd);
return FALSE;
}
}
close(fd);
// 检查开启转态并返回
return netif_is_up(ifname) == up;
}
// 5.获取指定网络接口MAC地址-----------------------------------
bool_t netif_get_mac(const char *ifname, MacAddr_t mac)
{
// 创建socket以进行ioctl调用
fd = if_socket();
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
return TRUE;
}
/*6. 设置指定网络接口MAC地址 X*/
bool_t netif_set_mac(const char *ifname, MacAddr_t mac)
{
// 创建socket以进行ioctl调用
fd = if_socket();
// 指定要修改的网络接口
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
// 准备好新的MAC地址
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
memcpy(ifr.ifr_hwaddr.sa_data, mac, ETH_ALEN);
// 调用ioctl设置MAC地址
if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
return TRUE;
}
/*7. 获取指定网络接口IP地址 J*/
bool_t netif_get_ip(const char *ifname, in_addr_t *ip)
{
// 创建socket以进行ioctl调用
fd = if_socket();
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFADDR, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
*ip = addr->sin_addr.s_addr;
return TRUE;
}
/* 8. 设置指定网络接口IP地址 */
bool_t netif_set_ip(const char *ifname, const char *in_addr_tip)
{
// 构建设置IP地址的命令字符串
char command[100];
snprintf(command, sizeof(command), "ifconfig %s %s", ifname, in_addr_tip);
// 执行命令,设置IP地址
int ret = system(command);
if (ret == -1)
{
printf("Failed to set IP address.\n");
return FALSE;
}
else
{
printf("IP address set successfully.\n");
return TRUE;
}
}
// 9.获取指定网络接口子网掩码 ---------------------------------
bool_t netif_get_mask(const char *ifname, in_addr_t *ip)
{
// 创建socket以进行ioctl调用
fd = if_socket();
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
close(fd);
struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_netmask;
*ip = addr->sin_addr.s_addr;
return TRUE;
}
/* 10. 设置指定网络接口子网掩码 */
bool_t netif_set_mask(const char *ifname, in_addr_t mask)
{
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
struct sockaddr_in *addr;
// 创建socket以进行ioctl调用
fd = if_socket();
// 清空ifr结构体并设置网络接口名称,例如 "eth0"
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
// 获取当前的子网掩码
if (ioctl(fd, SIOCGIFNETMASK, &ifr) == -1)
{
perror("ioctl");
close(fd);
exit(EXIT_FAILURE);
}
// 准备好 sockaddr_in 结构体设置子网掩码
addr = (struct sockaddr_in *)&ifr.ifr_addr;
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = mask;
// 使用SIOCSIFNETMASK ioctl命令设置子网掩码
if (ioctl(fd, SIOCSIFNETMASK, &ifr) == -1)
{
perror("ioctl SIOCSIFNETMASK failed");
close(fd);
return FALSE;
}
// 操作成功
close(fd);
return TRUE;
}
// 11.设置指定网络接口发送队列长度 ---------------------X-------
bool_t netif_set_txqueue(const char *ifname, uint32_t len)
{
// 构建设置IP地址的命令字符串
char command[100];
snprintf(command, sizeof(command), "ifconfig %s txqueuelen %d", ifname, len);
// 执行命令,设置IP地址
int ret = system(command);
if (ret == -1)
{
printf("Failed to set txqueuelen.\n");
return FALSE;
}
else
{
printf("TxqueueLen set successfully.\n");
return TRUE;
}
}
/* 12. 设置指定网络接口最大包负载MTU X */
bool_t netif_set_mtu(const char *ifname, uint32_t mtu)
{
// 为了设置MTU先关不端口
if (netif_up(ifname, 0) != TRUE)
{
return FALSE;
}
// 创建socket以进行ioctl调用
fd = if_socket();
// 清零结构体
memset(&ifr, 0, sizeof(ifr));
// 指定网络接口名称
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
// 获取当前接口参数
if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
{
perror("0 ioctl SIOCGIFMTU");
close(fd);
return FALSE;
}
printf("Current MTU of %s is %d chenge %d\n", ifname, ifr.ifr_mtu, mtu);
if (ifr.ifr_mtu == mtu)
{
printf("Current MTU of %s is %d == %d\n", ifname, ifr.ifr_mtu, mtu);
return TRUE;
}
// 设置新的MTU
ifr.ifr_mtu = mtu;
if (ioctl(fd, SIOCSIFMTU, &ifr) != 0)
{
perror("ioctl");
return FALSE;
}
// 再次获取新设置的MTU
if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
{
perror("ioctl");
close(fd);
return FALSE;
}
printf("New MTU of %s is %d\n", ifname, ifr.ifr_mtu);
// 关闭socket
close(fd);
// 设置MTU后再重启端口
netif_up(ifname, 1);
return TRUE;
}
// 13.获取收发包的数量 ------------------------------X-----
bool_t netif_get_bytes(char *ifname, unsigned long long *tx_bytes, unsigned long long *rx_bytes)
{
FILE *fp;
char buffer[1024];
char *line;
// 打开/proc/net/dev文件
fp = fopen("/proc/net/dev", "r");
if (fp == NULL)
{
perror("Error opening file");
return FALSE;
}
// 读取文件,直到找到相应的网络接口
while (fgets(buffer, sizeof(buffer), fp))
{
if (strstr(buffer, ifname))
{
// 这里假设行的格式是以下这种类型的:
// eth0: 123455 162100 ...(其他统计数据)
// 您可能需要根据实际情况调整 sscanf 的格式字符串来适配
// 解析接收和发送的数据包数量
line = strstr(buffer, ifname);
sscanf(line, "%*s %lu %*d %*d %*d %*d %*d %*d %*d %lu", rx_bytes, tx_bytes);
printf("Interface: %s\n", ifname);
break;
}
}
// 关闭文件
fclose(fp);
return TRUE;
}
// 14.获取无线是否连接(连接个数) -----------------------------------
int wlan_get_count(const char *ifname)
{
char cmd[256];
FILE *fp;
int count = 0;
char buffer[256];
// 创建获取无线设备列表的命令字符串
snprintf(cmd, sizeof(cmd), "iw dev %s station dump | grep Station | wc -l", ifname);
// 打开命令用于读取
if ((fp = popen(cmd, "r")) == NULL)
{
printf("Error opening pipe!\n");
return -1;
}
// 从管道中读取输出
if (fgets(buffer, sizeof(buffer), fp) != NULL)
{
// 将输出字符串转换为整数
count = atoi(buffer);
}
// 关闭管道
if (pclose(fp))
{
printf("Command not found or exited with error status\n");
return -1;
}
return count;
}
// 15.重新配置生效无线网络参数,当修改完无线网络参数后,可以调用此函数 ---------------
int wlan_restart(void)
{
// system("iwconfig wlan0 key s:your_key");
// system("iwconfig wlan0 essid your_essid");
if (netif_is_up("wlan0") == TRUE)
{
// 如果开启就关闭无线接口
int result_down = system("ifconfig wlan0 down");
if (result_down == -1)
{
perror("system");
return FALSE;
}
}
// 重新启动无线接口
int result_up = system("ifconfig wlan0 up");
if (result_up == -1)
{
perror("system");
return FALSE;
}
return TRUE;
}
// 16.重新配置网络参数,包括Ethernet、WiFi、Bluetooth、LTE等 当修改完网络参数后,可以调用此函数 -----------------------------------
int net_restart(void)
{
int result = system("systemctl restart NetworkManager");
if (result == -1)
{
perror("system");
return FALSE;
}
return TRUE;
}
// 17.获取无线连接信号强度(dBm) -----------------------------------
int wlan_get_signal(const char *ifname)
{
char cmd[1024];
FILE *fp;
char line[256];
int signal_strength = 0;
// 构建iwconfig命令,替换你的无线接口名(比如wlan0)
snprintf(cmd, sizeof(cmd), "iwconfig %s", ifname);
// 执行命令
fp = popen(cmd, "r");
if (fp == NULL)
{
perror("popen");
return EXIT_FAILURE;
}
// 读取命令返回的内容
while (fgets(line, sizeof(line), fp) != NULL)
{
char *ptr;
// 在返回的内容中查找"Signal level"字段
if ((ptr = strstr(line, "Signal level")) != NULL)
{
// 解析信号强度
sscanf(ptr, "Signal level=%d dBm", &signal_strength);
break;
}
}
// 关闭fp指针
pclose(fp);
return signal_strength;
}
2.3 测试代码 (简答写了一个将就着用吧>-<)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <linux/wireless.h>
#include "HRDSP.h"
typedef unsigned char MacAddr_t[6];
#define MAX_IP_LEN 15
int main(int argc, char *argv[])
{
typedef enum
{
FALSE,
TRUE
} bool_t;
char *ifname; // ens33 eth0 lo
printf("请设置要测试的端口(注:每次启动仅设置一次):\n");
char port_name[50];
scanf("%s", &port_name);
ifname = port_name;
printf("port_name=%s\n", ifname);
printf("进入测试\n");
MacAddr_t mac;
in_addr_t ip, mask;
unsigned long long tx_bytes, rx_bytes;
int is_break = 0;
int nunmber;
char command[256];
int isup;
char ipAddress[MAX_IP_LEN + 1]; // 最大IP地址长度为15,例如 255.255.255.255
unsigned char macAddr[6];
char mac_str[18];
struct ifreq ifr;
int s;
char subnet_mask[16], in_mtu[255]; // 用于存储用户输入的子网掩码字符串
// 无线循环
while (is_break == 0)
{
printf("请输入要测试的指令编号:\n");
scanf("%d", &nunmber);
switch (nunmber)
{
case 1:
//-------------------1. 检测指定网络接口是否存在--------------------------------------
printf("netif_is_exist Interface: %s\n", netif_is_exist(ifname) ? "exists" : "does not exist");
break;
case 2:
//-------------------2. 检测指定网络接口链路是否连接--------------------------------------
printf("Link status: %s\n", netif_is_link(ifname) ? "Connected" : "Disconnected");
break;
case 3:
//------------------3. 检测指定网络接口是否开启---------------------------------------
printf("netif_is_up Interface: %s\n", netif_is_up(ifname) ? "is up" : "is not up");
break;
case 4:
//--------------------4. 开启或关闭网络接口 0:关闭 、1:开启------------------os 需要判断关闭返回值-------------------
printf("开启或关闭网络接口 0:关闭-1:开启:\n");
scanf("%d", &isup);
printf("Interface up_dow: %s\n", netif_up(ifname, isup) ? "Success" : "Failed");
break;
case 5:
//-----------------------5.获取指定网络接口MAC地址----------------------------------
if (netif_get_mac(ifname, mac))
{
printf("5.netif_get_mac MAC address of %s: %02X:%02X:%02X:%02X:%02X:%02X\n",
ifname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
else
{
printf("Failed to get MAC address of %s\n", ifname);
}
break;
case 6:
//--------------------6. 设置指定网络接口MAC地址-------------------------------------
// Set MAC address
// 获取用户输入的MAC地址
printf("输入设置指定网络接口MAC地址 (e.g. 01:23:45:67:89:ab):\n");
scanf("%17s", &mac_str);
printf("输入mac_str: %s\n", mac_str);
if (sscanf(mac_str, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &macAddr[0],
&macAddr[1], &macAddr[2], &macAddr[3], &macAddr[4], &macAddr[5]) != 6)
{
fprintf(stderr, "Invalid MAC address format\n");
return FALSE;
}
// MacAddr_t mac = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
printf("Set MAC address: %s\n", netif_set_mac(ifname, macAddr) ? "Success" : "Failed");
break;
case 7:
//---------------------------7. 获取指定网络接口IP地址------------------------------
if (netif_get_ip(ifname, &ip))
{
struct in_addr addr;
addr.s_addr = ip;
printf("IP address of %s: %s\n", ifname, inet_ntoa(addr));
}
else
{
printf("Failed to get IP address of %s\n", ifname);
}
break;
case 8:
//----------------8. 设置指定网络接口IP地址-----------------------------------------
// Set IP address
printf("输入设置指定网络接口IP地址-169.254.127.228-:\n");
scanf("%15s", &ipAddress);
printf("Set IP address: %s\n", netif_set_ip(ifname, ipAddress) ? "Success" : "Failed");
break;
case 9:
//----------------9.获取指定网络接口子网掩码-----------------------------------------
if (netif_get_mask(ifname, &mask))
{
struct in_addr addr;
addr.s_addr = mask;
printf("Subnet mask of %s: %s\n", ifname, inet_ntoa(addr));
}
else
{
printf("Failed to get subnet mask of %s\n", ifname);
}
break;
case 10:
//-----------------10. 设置指定网络接口子网掩码----------------------------------------
// Set subnet mask
printf("输入设置指定网络接口子网掩码-255.255.0.0-:\n");
scanf("%15s", &subnet_mask);
in_addr_t subnetMask = inet_addr(subnet_mask);
printf("Set subnet mask: %s\n", netif_set_mask(ifname, subnetMask) ? "Success" : "Failed");
break;
case 11:
//------------------11.设置指定网络接口发送队列长度---------------------------------------
printf("输入设置指定网络接口发送队列长度100:\n");
uint32_t *len;
scanf("%d", &len);
if (netif_set_txqueue(ifname, len))
{
printf("Successfully set tx queue length\n");
}
else
{
printf("Failed to set tx queue length\n");
}
break;
case 12:
//-----------------12. 设置指定网络接口最大包负载MTU----------------------------------------
// Set MTU
printf("输入设置指定网络接口最大包负载MTU=1500:\n");
scanf("%9s", &in_mtu);
uint32_t mtu = atoi(in_mtu);
printf("Set MTU: %s\n", netif_set_mtu(ifname, mtu) ? "Success" : "Failed");
break;
case 13:
//------------------------13.获取收发包的数量---------------------------------
if (netif_get_bytes(ifname, &tx_bytes, &rx_bytes))
{
printf("TX bytes of %s: %llu\n", ifname, tx_bytes);
printf("RX bytes of %s: %llu\n", ifname, rx_bytes);
}
else
{
printf("Failed to get TX/RX bytes of %s\n", ifname);
}
break;
case 14:
//------------------------14.获取无线是否连接(连接个数)---------------------------------
{
int count = wlan_get_count(ifname);
if (count >= 0)
{
printf("Number of wireless connections on %s: %d\n", ifname, count);
}
else
{
printf("Could not get the wireless connection count.\n");
}
}
break;
case 15:
//------------------------15.重新配置生效无线网络参数,当修改完无线网络参数后,可以调用此函数---------------------------------
printf(wlan_restart() == 1 ? "Wireless network restarted successfully.\n" : "Failed to restart wireless network.\n");
break;
case 16:
//------------------------16.重新配置网络参数,包括Ethernet、WiFi、Bluetooth、LTE等 当修改完网络参数后,可以调用此函数---------------------------------
printf(net_restart() == 1 ? "Wireless network restarted successfully.\n" : "Failed to restart wireless network.\n");
break;
case 17:
//------------------------17.获取无线连接信号强度(dBm)---------------------------------
{
int signal = wlan_get_signal(ifname);
if (signal != 0)
{
printf("Current signal strength of interface '%s': %d dBm\n", ifname, signal);
}
else
{
printf("Could not get signal strength for the interface '%s'\n", ifname);
}
}
break;
default:
// 结束循环
goto end_of_while;
break;
}
}
end_of_while:
printf("结束测试:\n");
return 0;
}