【Linux 应用】网络相关开发---ip、网关、掩码、dns、mac的获取和设置,以及dhcp动态获取

最近开始调试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;
}

结束语

这篇文章主要是记录一下,方便以后回忆和查阅,写的不尽详细,又不懂得欢迎留言交流。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值