Chinaunix首页 | 论坛 | 博客
  • 博客访问: 95537
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 90
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-07 19:35
文章分类
文章存档

2015年(11)

2014年(18)

我的朋友

分类: LINUX

2015-03-03 09:53:54

原文地址:ifconfig 的简单实现 作者:yishuihe

 一般,用户在shell中使用ifconfig命令对网络接口进行参数配置,及接口的打开,关闭等操作。ifconfig实现网络接口配置的原理在于代表网络接口的结构体struct net_device的成员ip_ptr。前文已经讲过,ip_ptr实际指向的是一个结构体struct in_device,in_device有一个成员struct in_ifaddr *ifa_list,它指向一个链表,链表的每一项代表一个IP地址。对这个链表操作即可实现对网络接口的配置。
    网络接口的操作命令按功能可以分为两组,第一组为查询命令:SIOCGIFADDR,SIOCGIFBRDADDR,SIOCGIFDSTADDR, SIOCGIFNETMASK。分别用于查询网络接口的IP地址,广播地址,目的地址,子网掩码。第二组为设置命令:SIOCSIFADDR, SIOCSIFFLAGS,SIOCSIFBRDADDR,SIOCSIFNETMASK,SIOCSIFDSTADDR。分别用于设置网络接口的IP地址,标志位,广播地址,子网掩码,目的地址。这些命令所要查询和设置的信息全部在结构体struct in_ifaddr中。
    用户空间的应用程序通过系统调用ioctl使用这些命令,ioctl的函数原型如下:
        #include
        int ioctl(int d, int request, ...);
    以上九个命令使用的参数为同一类型,即struct ifreq,其定义可在include/linux/if.h中找到。
    下面是两组命令在my_inet模块中的使用示例,因为整个my_inet模块代码还很不完善,通过my_inet模块新添加的IP地址并不能正常使用。
#include
#include
#include
#include
#include "my_inet.h"
#include
#include
#include

int main()
{
    struct ifreq req;
    strncpy( req.ifr_name, "eth0", IFNAMSIZ );
    struct sockaddr_in *sin;

    int fd = socket( MY_PF_INET, SOCK_RAW, MY_IPPROTO_ICMP );
    if( fd < 0 ){
        perror("error: ");
        return -1;
    }

    sin = (struct sockaddr_in *)&req.ifr_addr;
    if( ioctl( fd, SIOCGIFADDR, &req) == 0 )
        printf("%s\n", inet_ntoa(sin->sin_addr.s_addr) );
    else
        perror("ioctl error: ");

    sin = (struct sockaddr_in *)&req.ifr_broadaddr;
    if( ioctl( fd, SIOCGIFBRDADDR, &req) == 0 )
        printf("%s\n", inet_ntoa(sin->sin_addr.s_addr) );
    else
        perror("ioctl error: ");

    sin = (struct sockaddr_in *)&req.ifr_dstaddr;
    if( ioctl( fd, SIOCGIFDSTADDR, &req) == 0 )
        printf("%s\n", inet_ntoa(sin->sin_addr.s_addr) );
    else
        perror("ioctl error: ");

    sin = (struct sockaddr_in *)&req.ifr_netmask;
    if( ioctl( fd, SIOCGIFNETMASK, &req) == 0 )
        printf("%s\n", inet_ntoa(sin->sin_addr.s_addr) );
    else
        perror("ioctl error: ");

    close( fd );
    return 0;
}

#include
#include
#include
#include
#include "my_inet.h"
#include
#include
#include

int main()
{
    struct ifreq req;
    strncpy( req.ifr_name, "eth0:0", IFNAMSIZ );
    struct sockaddr_in *sin;

    int fd = socket( MY_PF_INET, SOCK_RAW, MY_IPPROTO_ICMP );
    if( fd < 0 ){
        perror("error: ");
        return -1;
    }

    sin = (struct sockaddr_in *)&req.ifr_addr;
    sin->sin_family = MY_PF_INET;
    if( inet_aton("172.16.48.10", &sin->sin_addr) == 0 ){
        perror("inet_aton error: ");
        return -1;
    }
    if( ioctl( fd, SIOCSIFADDR, &req ) == 0 ){
        printf("success!\n");
    }else{
        perror("ioctl failed: ");
    }

    req.ifr_flags = IFF_UP;
    if( ioctl( fd, SIOCSIFFLAGS, &req ) == 0 ){
        printf("success!\n");
    }else{
        perror("ioctl failed: ");
    }

    sin->sin_family = MY_PF_INET;
    if( inet_aton("172.16.48.255", &sin->sin_addr) == 0 ){
        perror("inet_aton error: ");
        return -1;
    }
    if( ioctl( fd, SIOCSIFBRDADDR, &req ) == 0 ){
        printf("success!\n");
    }else{
        perror("ioctl failed: ");
    }

    sin->sin_family = MY_PF_INET;
    if( inet_aton("255.255.255.0", &sin->sin_addr) == 0 ){
        perror("inet_aton error: ");
        return -1;
    }
    if( ioctl( fd, SIOCSIFNETMASK, &req ) == 0 ){
        printf("success!\n");
    }else{
        perror("ioctl failed: ");
    }

    close( fd );
    return 0;
}
    要想让上述的代码发挥实际的作用,只要把所有的MY_PF_INET改成PF_INET即可。功能再作增强,就是一个ifconfig程序了。
阅读(1531) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~