最近开始调试Linux 的测试版,需要开发网络设置相关功能。其实这一块以前也做过,但是都忘记了,可见沉淀的重要性。
1、ip、掩码设置和获取
通过int ioctl(int d, int request, ...);这个函数可以获取到。
其中:
IP设置:SIOCGIFADDR
掩码设置:SIOCGIFNETMASK
mac设置:SIOCGIFHWADDR
其他具体如下:
2、DNS获取和设置
dns设置和获取时通过读写/etc/resolv.conf文件来实现的
# cat /etc/resolv.conf
nameserver 202.96.134.133
nameserver 202.96.128.166
nameserver 202.96.134.133 # eth0
nameserver 202.96.128.166 # eth0
/tmp/resolv.conf文件也是可以的
# ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 18 Apr 22 2020 /etc/resolv.conf -> ../tmp/resolv.conf
3、网关获取
通过ip route 命令来获取route,以及字符串处理来获取默认网关(default)
4、dhcp动态获取
通过udhcpc 命令来实现dhcp动态获取的
5、代码实现
1、头文件
#ifndef __NET_MANAGER_H__
#define __NET_MANAGER_H__
#define DEFAULT_ETH "eth0"
#define IP_ADDE_COUNT 16
#define IP_SET_STATIC 1
#define IP_SET_AUTO 0
int start_dhcp(char* net_name);
int end_dhcp();
int is_valid_netmask(char* netmask);
int get_ip(char* ip,int length);
int get_ip_netmask(char* ip,int length);
int get_mac(char* addr,int length);
int set_ip_netmask(char* ip,int length);
int set_ip(char* ip,int length);
int set_gateway(char* gateway,int length);
int get_gateway(char* gateway, int length);
int get_dns(char* dns1, int length_dns1, char* dns2, int length_dns2);
int set_dns(const char *dns1,int length_dns1, const char *dns2, int length_dns2);
void set_net(char *ip_addr,int length_ip_addr,char *netmask,int length_netmask,char *gateway,int length_gateway,char *dns1,int length_dns1,char *dns2,int length_dns2);
int connect_check_real ();
int device_check_if_conn(char* ifname);
void net_init();
#endif
2、实现文件
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <ctype.h>
#include <net/route.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <sys/wait.h>
#if defined(__GLIBC__) && __GLIBC__ >=2 && __GLIBC_MINOR__ >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h>
#else
#include <sys/types.h>
#include <netinet/if_ether.h>
#endif
#include "netManager.h"
#include "userInfo.h"
#include "debugUtils.h"
#define NET_MANAGER_FALSE -1
#define NET_MANAGER_TRUE 0
static int set_addr(char* ip, int flag);
static int get_addr(char *addr, int length, int flag);
/*
*检测ips是否合法
*/
static int is_valid_ip(const char* ipaddr)
{
int ret = 0;
struct in_addr inp;
char buf[64] = {0};
int ip1,ip2,ip3,ip4;
if(ipaddr == NULL){
printf("is_valid_ip error: ipaddr is NULL \n");
return NET_MANAGER_FALSE;
}
sscanf(ipaddr, "%03d.%03d.%03d.%03d", &ip1,&ip2,&ip3,&ip4);
snprintf((char *)buf, sizeof(buf), "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
ret = inet_aton(buf, &inp);
if (0 == ret)
{
return NET_MANAGER_FALSE;
}
return NET_MANAGER_TRUE;
}
/*
* 先验证是否为合法IP,然后将掩码转化�?2无符号整型,取反�?00...00111...1�?
* 然后再加1�?0...01000...0,此时为2^n,如果满足就为合法掩�?
*
* */
int is_valid_netmask(char* netmask)
{
if(netmask == NULL){
printf("is_valid_ip error: ipaddr is NULL \n");
return NET_MANAGER_FALSE;
}
if(is_valid_ip(netmask) == 0)
{
unsigned long b = 0, i, n[4];
sscanf(netmask, "%u.%u.%u.%u", &n[3], &n[2], &n[1], &n[0]);
for(i = 0; i < 4; ++i) //将子网掩码存�?2位无符号整型
{
b += n[i] << (i * 8);
}
b = ~b + 1;
if((b & (b - 1)) == 0) //判断是否�?^n
return NET_MANAGER_TRUE;
}
GUI_DEBUG("============is_valid_netmask=======%s=============\n",netmask);
return NET_MANAGER_FALSE;
}
int end_dhcp()
{
int ret = NET_MANAGER_FALSE;
if(access("/var/run/udhcpc.pid",R_OK) == -1){
return NET_MANAGER_TRUE;
}
ret = system("cat /var/run/udhcpc.pid|xargs kill -9");
if(ret < 0)
{
perror("end_dhcp error");
return NET_MANAGER_FALSE;
}
return NET_MANAGER_TRUE;
}
/*
*dhcp动态获取网络
*/
int start_dhcp(char* net_name)
{
int ret = NET_MANAGER_FALSE;
char cmd[IP_ADDE_COUNT+128] = {0};
end_dhcp();
if(NULL == net_name ||strlen(net_name) == 0){
snprintf(cmd, sizeof(cmd),"busybox udhcpc -b -q -i %s -s /etc/simple.script -p /var/run/udhcpc.pid",DEFAULT_ETH);
cmd[sizeof(cmd) -1] ='\0';
}else{
snprintf(cmd, sizeof(cmd),"busybox udhcpc -b -q -i %s -s /etc/simple.script -p /var/run/udhcpc.pid",net_name);
cmd[sizeof(cmd) -1] ='\0';
}
ret = system(cmd);
if(ret==-1){
GUI_DEBUG("run system command error");
}else{
if(WIFEXITED(ret)){
if(0==WEXITSTATUS(ret)){
GUI_DEBUG("cmd: %s", cmd);
ret=NET_MANAGER_TRUE;
}else{
//GLOG_DEBUG("%s connect to internet fail", ifname);
}
}else{
GUI_DEBUG("exit Code status %d", WEXITSTATUS(ret));
}
}
return ret;
}
/*
*获取ip
*/
int get_ip(char* ip,int length)
{
return get_addr(ip, length, SIOCGIFADDR);
}
/*
*获取子网掩码
*/
int get_ip_netmask(char* ip,int length)
{
return get_addr(ip, length, SIOCGIFNETMASK);
}
/*
*获取mac
*/
int get_mac(char* addr,int length)
{
return get_addr(addr, length, SIOCGIFHWADDR);
}
/*
*根据参数获取�?
*/
static int get_addr(char *addr, int length, int flag)
{
int sockfd = 0;
struct sockaddr_in *sin;
struct ifreq ifr;
if(addr == NULL){
printf("get_addr error:addr is NULL\n");
return NET_MANAGER_FALSE;
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket error!\n");
return NET_MANAGER_FALSE;
}
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, (sizeof(ifr.ifr_name) - 1), "%s", DEFAULT_ETH);
if(ioctl(sockfd, flag, &ifr) < 0 )
{
perror("ioctl error!\n");
close(sockfd);
return NET_MANAGER_FALSE;
}
close(sockfd);
if (SIOCGIFHWADDR == flag){
memcpy((void *)addr, (const void *)&ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
GUI_DEBUG("mac address: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
}else{
sin = (struct sockaddr_in *)&ifr.ifr_addr;
//snprintf((char *)addr, IP_ADDE_COUNT, "%s", inet_ntoa(sin->sin_addr));
long ipaddr = inet_addr(inet_ntoa(sin->sin_addr));
snprintf((char *)addr, length, "%03d.%03d.%03d.%03d", (ipaddr >> 0) & 0xFF, (ipaddr >> 8) & 0xFF, (ipaddr >> 16) & 0xFF, (ipaddr >> 24) & 0xFF);
GUI_DEBUG("============get_addr======= %s =============\n", addr);
if(is_valid_ip(addr) != 0){
return NET_MANAGER_FALSE;
}
}
return NET_MANAGER_TRUE;
}
/*
*设置子网掩码
*/
int set_ip_netmask(char* ip,int length)
{
int ip1,ip2,ip3,ip4;
if(NULL == ip){
printf("set_ip_netmask error: ip is NULL \n");
return NET_MANAGER_FALSE;
}
sscanf(ip, "%03d.%03d.%03d.%03d", &ip1,&ip2,&ip3,&ip4);
snprintf((char *)ip, length, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
GUI_DEBUG("============set_ip_netmask======= %s =============\n", ip);
return set_addr(ip, SIOCSIFNETMASK);
}
/*
*设置ip
*/
int set_ip(char* ip,int length)
{
int ip1,ip2,ip3,ip4;
if(NULL == ip){
printf("set_ip_netmask error: ip is NULL \n");
return NET_MANAGER_FALSE;
}
sscanf(ip, "%03d.%03d.%03d.%03d", &ip1,&ip2,&ip3,&ip4);
snprintf((char *)ip, length, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
GUI_DEBUG("============set_ip======= %s =============\n", ip);
return set_addr(ip, SIOCSIFADDR);
}
/*
*根据参数设置
*/
static int set_addr(char* ip, int flag)
{
struct ifreq ifr;
struct sockaddr_in sin;
int sockfd;
if(ip == NULL){
printf("set_addr error: ip is NULL\n");
return NET_MANAGER_FALSE;
}
if (is_valid_ip(ip) != 0)
{
printf("ip was invalid!\n");
return NET_MANAGER_FALSE;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd == -1){
fprintf(stderr, "Could not get socket.\n");
perror("eth0\n");
return NET_MANAGER_FALSE;
}
snprintf(ifr.ifr_name, (sizeof(ifr.ifr_name) - 1), "%s", DEFAULT_ETH);
/* Read interface flags */
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
fprintf(stderr, "ifdown: shutdown ");
perror(ifr.ifr_name);
close(sockfd);
return NET_MANAGER_FALSE;
}
memset(&sin, 0, sizeof(struct sockaddr));
sin.sin_family = AF_INET;
inet_aton(ip, &sin.sin_addr.s_addr);
memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));
if (ioctl(sockfd, flag, &ifr) < 0){
fprintf(stderr, "Cannot set IP address. ");
perror(ifr.ifr_name);
close(sockfd);
return NET_MANAGER_FALSE;
}
close(sockfd);
return NET_MANAGER_TRUE;
}
/*
*设置网关
*/
int set_gateway(char* gateway,int length)
{
int s;
struct rtentry rt;
struct sockaddr_in sockaddr;
int ip1,ip2,ip3,ip4;
if((NULL == gateway) || (length == 0)){
printf("set_gateway: gateway error.\n");
return NET_MANAGER_FALSE;
}
sscanf(gateway, "%03d.%03d.%03d.%03d", &ip1,&ip2,&ip3,&ip4);
snprintf((char *)gateway, length, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
GUI_DEBUG("============set_gateway======= %s =============\n", gateway);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
{
perror("Socket create error.\n");
return NET_MANAGER_FALSE;
}
memset(&rt, 0, sizeof(struct rtentry));
memset(&sockaddr, 0, sizeof(struct sockaddr_in));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = 0;
if(inet_aton(gateway, &sockaddr.sin_addr)<0)
{
perror("inet_aton error\n" );
close(s);
return NET_MANAGER_FALSE;
}
memcpy ( &rt.rt_gateway, &sockaddr, sizeof(struct sockaddr_in));
((struct sockaddr_in *)&rt.rt_dst)->sin_family=AF_INET;
((struct sockaddr_in *)&rt.rt_genmask)->sin_family=AF_INET;
rt.rt_flags = RTF_GATEWAY;
if (ioctl(s, SIOCADDRT, &rt)<0)
{
perror("ioctl(SIOCADDRT) error in set_default_route\n");
close(s);
return NET_MANAGER_FALSE;
}
close(s);
return NET_MANAGER_TRUE;
}
/*
*获取网关
*/
int get_gateway(char* gateway, int length)
{
FILE *fp;
char buf[512];
char cmd[128];
char *tmp;
if(gateway == NULL){
printf("get_gateway error: gateway is NULL\n");
return NET_MANAGER_FALSE;
}
strcpy(cmd, "busybox ip route");
fp = popen(cmd, "r");
if(NULL == fp)
{
perror("popen error");
return NET_MANAGER_FALSE;
}
while(fgets(buf, sizeof(buf), fp) != NULL)
{
tmp =buf;
while(*tmp && isspace(*tmp))
++ tmp;
if(strncmp(tmp, "default", strlen("default")) == 0){
GUI_DEBUG("default gateway:%s\n", buf);
sscanf(buf, "%*s%*s%s", gateway);
long ipaddr = inet_addr(gateway);
snprintf((char *)gateway, length, "%03d.%03d.%03d.%03d", (ipaddr >> 0) & 0xFF, (ipaddr >> 8) & 0xFF, (ipaddr >> 16) & 0xFF, (ipaddr >> 24) & 0xFF);
GUI_DEBUG("default gateway:%s\n", gateway);
break;
}
}
pclose(fp);
return NET_MANAGER_TRUE;
}
/*
*获取dns
*/
int get_dns(char* dns1, int length_dns1, char* dns2, int length_dns2)
{
FILE *fp;
char buf[512];
char cmd[128];
int i = 0;
if(dns1 == NULL || NULL == dns2){
printf("get_dns error: dns is NULL \n");
return NET_MANAGER_FALSE;
}
strcpy(cmd, "cat /tmp/resolv.conf");
fp = popen(cmd, "r");
if(NULL == fp)
{
perror("popen error");
return NET_MANAGER_FALSE;
}
while(fgets(buf, sizeof(buf), fp) != NULL)
{
if(strlen(buf) == 0 || strncmp(buf, "nameserver",strlen("nameserver")) != 0){
continue;
}
if(i >= 2){
i = 0;
}
if(i == 0){
sscanf(buf, "%*s%s", dns1);
long ipaddr = inet_addr(dns1);
snprintf((char *)dns1, length_dns1, "%03d.%03d.%03d.%03d", (ipaddr >> 0) & 0xFF, (ipaddr >> 8) & 0xFF, (ipaddr >> 16) & 0xFF, (ipaddr >> 24) & 0xFF);
}else{
sscanf(buf, "%*s%s", dns2);
long ipaddr = inet_addr(dns2);
snprintf((char *)dns2, length_dns2, "%03d.%03d.%03d.%03d", (ipaddr >> 0) & 0xFF, (ipaddr >> 8) & 0xFF, (ipaddr >> 16) & 0xFF, (ipaddr >> 24) & 0xFF);
}
i++;
}
pclose(fp);
return NET_MANAGER_TRUE;
}
/*
*设置dns
*/
int set_dns(const char *dns1,int length_dns1, const char *dns2, int length_dns2)
{
int ret = NET_MANAGER_TRUE;
char cmd[128] = {0};
int ip1,ip2,ip3,ip4;
if(NULL == dns1 || NULL == dns2){
printf("set_dns error: dns1 or dns2 is NULL \n");
return NET_MANAGER_FALSE;
}
sscanf(dns1, "%03d.%03d.%03d.%03d", &ip1,&ip2,&ip3,&ip4);
snprintf((char *)dns1, length_dns1,"%d.%d.%d.%d", ip1, ip2, ip3, ip4);
sscanf(dns2, "%03d.%03d.%03d.%03d", &ip1,&ip2,&ip3,&ip4);
snprintf((char *)dns2, length_dns2,"%d.%d.%d.%d", ip1, ip2, ip3, ip4);
GUI_DEBUG("============set_dns====dns1=== %s =============\n", dns1);
GUI_DEBUG("============set_dns====dns2=== %s =============\n", dns2);
if(sizeof(dns1) == 0)
{
return;
}
snprintf(cmd, sizeof(cmd),"echo \"nameserver %s\" > /tmp/resolv.conf",dns1);
ret = system(cmd);
if(ret < 0)
{
perror("route error");
return NET_MANAGER_FALSE;
}
snprintf(cmd, sizeof(cmd), "echo \"nameserver %s\" >> /tmp/resolv.conf",dns2);
//strcpy(cmd, "route add default gw ");
//strcat(cmd, szGateWay);
ret = system(cmd);
if(ret < 0)
{
perror("set_dns error");
return NET_MANAGER_FALSE;
}
return ret;
}
/*
*设置静态IP网络
*/
void set_net(char *ip_addr,int length_ip_addr,char *netmask,int length_netmask,char *gateway,int length_gateway,char *dns1,int length_dns1,char *dns2,int length_dns2)
{
if(ip_addr != NULL){
set_ip(ip_addr,length_ip_addr);
}
if((netmask == NULL) && is_valid_netmask(netmask) == 0){
set_ip_netmask(netmask, length_netmask);
}else{
GUI_DEBUG("g_mask_addr is error\n");
}
if(gateway != NULL){
set_gateway(gateway, length_gateway);
}
if((dns1 != NULL) && (dns2 != NULL)){
set_dns(dns1, length_dns1, dns2, length_dns2);
}
return;
}
void net_init()
{
IpInfo_S netInfo = getIpinfo();
if(netInfo.m_netMode == IP_SET_STATIC){
GUI_DEBUG("net_init is IP_SET_STATIC\n");
set_net(netInfo.m_ipAddr, strlen(netInfo.m_ipAddr), netInfo.m_Netmask, strlen(netInfo.m_Netmask), netInfo.m_gateWay, strlen(netInfo.m_gateWay), netInfo.m_Dns1,strlen(netInfo.m_Dns1), netInfo.m_Dns2,strlen(netInfo.m_Dns2));
}else{
GUI_DEBUG("net_init is IP_SET_AUTO\n");
start_dhcp(DEFAULT_ETH);
}
return;
}
int connect_check_real ()
{
int ret = -1;
int fp;
char status[10];
//一定要只读模式打开,读写模式打开不可以
fp = open ("/sys/class/net/eth0/operstate",O_RDONLY);
if (fp<0) {
printf("open file operstate failure%d\n",fp);
return;
}
memset(status,0,sizeof(status));
ret = read (fp,status,10);
printf("status:%s\n",status);
if (NULL != strstr(status,"up")){
printf("on line now \n");
ret = 0;
}
else if (NULL != strstr(status,"down")){
printf("off off \n");
}
else{
printf("unknow error\n");
}
close (fp);
return ret;
}
int device_check_if_conn(char* ifname)
{
pid_t status;
uint8_t ret=-1, i=0;
char cmd[256];
char serverip[3][32]={"114.114.114.114","8.8.8.8","223.5.5.5"};
for(i=0;i<3;i++){
snprintf(cmd, sizeof(cmd),"busybox ping -I %s -w 1 -c 1 %s 1>/dev/null 2>&1", ifname, serverip[i]);
status=system(cmd);
if(status==-1){
GUI_DEBUG("run system command error");
}else{
if(WIFEXITED(status)){
if(0==WEXITSTATUS(status)){
GUI_DEBUG("%s connect to internet ok", ifname);
GUI_DEBUG("cmd: %s", cmd);
ret=0;
break;
}else{
//GLOG_DEBUG("%s connect to internet fail", ifname);
}
}else{
GUI_DEBUG("exit Code status %d", WEXITSTATUS(status));
}
}
}
return ret;
}
int check_net()
{
if(connect_check_real() != 0){
return -1;
}
if(device_check_if_conn("eth0") != 0){
return 0;
}
return 1;
}
3、测试代码
#include <stdio.h>
#include "netManager.h"
void set_net();
int main(int argc, char *argv[])
{
set_net();
get_dhcp(NULL);
get_net_info();
return 0;
}
void set_net()
{
char g_mask_addr[IP_ADDE_COUNT] = "255.255.0.0";
char g_ip_addr[IP_ADDE_COUNT] = "172.30.16.68";
char g_gateway_addr[IP_ADDE_COUNT] = "172.30.15.253";
char g_dns_addr[2][IP_ADDE_COUNT] = {"8.8.8.8","114.114.114.144"};
set_ip(g_ip_addr);
if(is_valid_netmask(g_mask_addr) == 0){
set_ip_netmask(g_mask_addr);
}else{
printf("g_mask_addr is error\n");
}
set_gateway(g_gateway_addr);
set_dns(g_dns_addr[0],g_dns_addr[1]);
return;
}
void get_net_info()
{
char s_ip_addr[IP_ADDE_COUNT] = {0},s_mask_addr[IP_ADDE_COUNT] = {0},s_mac_addr[6] = {0}, \
s_gateway_addr[IP_ADDE_COUNT] = {0},s_dns_addr[2][IP_ADDE_COUNT] = {0};
get_ip(s_ip_addr);
get_mac(s_mac_addr);
get_ip_netmask(s_mask_addr);
get_gateway(s_gateway_addr);
get_dns(s_dns_addr);
printf("=========================%s=====================\n",s_ip_addr);
printf("=========================%s=====================\n",s_mask_addr);
printf("=========================%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x=====================\n", s_mac_addr[0],s_mac_addr[1],s_mac_addr[2],s_mac_addr[3],s_mac_addr[4],s_mac_addr[5]);
printf("=========================%s=====================\n",s_gateway_addr);
printf("=========================%s=====================\n",s_dns_addr[0]);
printf("=========================%s=====================\n",s_dns_addr[1]);
return;
}
结束语
这篇文章主要是记录一下,方便以后回忆和查阅,写的不尽详细,又不懂得欢迎留言交流。