IOCTL獲取和配置IP地址/子網掩碼/網關

OS:LINUX

這部分代碼包含:
1.獲取IP地址,子網掩碼,物理地址。
2.配置IP地址,子網掩碼,網關等。
3.IP地址合法驗證和子網掩碼驗證。

TIPS:部分代碼摘自網上,代碼已測試通過。


#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>
#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 "xxx_ip.h"

static int set_addr(unsigned char ip[16], int flag);
static int get_addr(unsigned char ip[16], int flag);

int get_ip(unsigned char ip[16])
{
    return get_addr(ip, SIOCGIFADDR);
}

int get_ip_netmask(unsigned char ip[16])
{
    return get_addr(ip, SIOCGIFNETMASK);
}

int get_mac(unsigned char addr[6])
{
    return get_addr(addr, SIOCGIFHWADDR);
}

static int get_addr(unsigned char *addr, int flag)
{
    SINT32 sockfd = 0;
    struct sockaddr_in *sin;
    struct ifreq ifr;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket error!\n");
        return 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 FALSE;
    }
    close(sockfd);

    if (SIOCGIFHWADDR == flag){
        memcpy((void *)addr, (const void *)&ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
        /*printf("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_LENGTH, "%s", inet_ntoa(sin->sin_addr));
    }

    return TRUE;
}

int is_valid_ip(unsigned char ipaddr[16])
{
    int ret = 0;
    struct in_addr inp;
    ret = inet_aton(ipaddr, &inp);
    if (0 == ret)
    {
        return FALSE;
    }
    else
    {
        printf("inet_aton:ip=%lu\n",ntohl(inp.s_addr));
    }

    return TRUE;
}

/*
 * 先驗證是否爲合法IP,然後將掩碼轉化成32無符號整型,取反爲000...00111...1,
 * 然後再加1爲00...01000...0,此時爲2^n,如果滿足就爲合法掩碼
 *
 * */
int is_valid_netmask(unsigned char netmask[16])
{
    if(is_valid_ip(netmask) > 0)
    {
        unsigned int 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) //將子網掩碼存入32位無符號整型
            b += n[i] << (i * 8);
        b = ~b + 1;
        if((b & (b - 1)) == 0) //判斷是否爲2^n
            return TRUE;
    }

    return FALSE;
}


int set_ip_netmask(unsigned char ip[16])
{
    return set_addr(ip, SIOCSIFNETMASK);
}

int set_ip(unsigned char ip[16])
{
    return set_addr(ip, SIOCSIFADDR);
}

static int set_addr(unsigned char ip[16], int flag)
{
    struct ifreq ifr;
    struct sockaddr_in sin;
    int sockfd;

    if (is_valid_ip(ip) < 0)
    {
        printf("ip was invalid!\n");
        return FALSE;
    }

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd == -1){
        fprintf(stderr, "Could not get socket.\n");
        perror("eth0\n");
        return 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);
        return 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);
        return FALSE;
    }

    return TRUE;
}


int set_gateway(unsigned char ip[16])
{
    int sockFd;
    struct sockaddr_in sockaddr;
    struct rtentry rt;

    if (is_valid_ip(ip) < 0)
    {
        printf("gateway was invalid!\n");
        return FALSE;
    }

    sockFd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockFd < 0)
    {
        perror("Socket create error.\n");
        return 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(ip, &sockaddr.sin_addr)<0)
    {
        perror("inet_aton error\n" );
        close(sockFd);
        return 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(sockFd, SIOCADDRT, &rt)<0)
    {
        perror("ioctl(SIOCADDRT) error in set_default_route\n");
        close(sockFd);
        return FALSE;
    }

    return TRUE;
}


發佈了141 篇原創文章 · 獲贊 108 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章