zoukankan      html  css  js  c++  java
  • ifconfig调用过程

    copy from :https://blog.csdn.net/liangdsing/article/details/70159314

    ifconfig命令是可以查看当前网络设备信息,在openwrt环境中,ifconfig源码位于busybox文件夹下

    找到入口函数ifconfig_main,位于ifconfig.c文件中

    int ifconfig_main(int argc UNUSED_PARAM, char **argv)
    {
    struct ifreq ifr;
    struct sockaddr_in sai;
    #if ENABLE_FEATURE_IFCONFIG_HW
    struct sockaddr sa;
    #endif
    const struct arg1opt *a1op;
    const struct options *op;
    int sockfd; /* socket fd we use to manipulate stuff with */
    int selector;
    #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
    unsigned int mask;
    unsigned int did_flags;
    unsigned int sai_hostname, sai_netmask;
    #else
    unsigned char mask;
    unsigned char did_flags;
    #endif
    char *p;
    /*char host[128];*/
    const char *host = NULL; /* make gcc happy */

    did_flags = 0;
    #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
    sai_hostname = 0;
    sai_netmask = 0;
    #endif

    /* skip argv[0] */
    ++argv;

    #if ENABLE_FEATURE_IFCONFIG_STATUS
    if (argv[0] && (argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2])) {
    interface_opt_a = 1;
    ++argv;
    }
    #endif

    if (!argv[0] || !argv[1]) { /* one or no args */
    #if ENABLE_FEATURE_IFCONFIG_STATUS
    return display_interfaces(argv[0] /* can be NULL */);
    #else
    bb_error_msg_and_die("no support for status display");
    #endif
    }

    若未配置任何信息则进入下面函数


    int FAST_FUNC display_interfaces(char *ifname)
    {
    int status;

    status = if_print(ifname);

    return (status < 0); /* status < 0 == 1 -- error */
    }
    若提供端口名字则查看对应名字的设备端口信息
    static int if_print(char *ifname)
    {
    struct interface *ife;
    int res;

    if (!ifname) {
    /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/
    if (!int_list && (if_readlist() < 0))
    return -1;
    for (ife = int_list; ife; ife = ife->next) {
    int err = do_if_print(ife); /*, &interface_opt_a);*/
    if (err)
    return err;
    }
    return 0;
    }
    ife = lookup_interface(ifname);
    res = do_if_fetch(ife);
    if (res >= 0)
    ife_print(ife);
    return res;
    }


    读取设备名称信息,首先从proc文件系统读取,若失败,则通过ioctl读取内核内的设备信息
    static int if_readlist(void)
    {
    int err = if_readlist_proc(NULL);
    /* Needed in order to get ethN:M aliases */
    if (!err)
    err = if_readconf();
    return err;
    }

    之后更新这些设备名称从通过ioctl从内核中读取详细信息
    static int if_fetch(struct interface *ife)
    {
    struct ifreq ifr;
    char *ifname = ife->name;
    int skfd;

    skfd = xsocket(AF_INET, SOCK_DGRAM, 0);

    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
    close(skfd);
    return -1;
    }
    ife->flags = ifr.ifr_flags;

    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    memset(ife->hwaddr, 0, 32);
    if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0)
    memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);

    ife->type = ifr.ifr_hwaddr.sa_family;

    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    ife->metric = 0;
    if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0)
    ife->metric = ifr.ifr_metric;

    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    ife->mtu = 0;
    if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0)
    ife->mtu = ifr.ifr_mtu;

    memset(&ife->map, 0, sizeof(struct ifmap));
    #ifdef SIOCGIFMAP
    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
    ife->map = ifr.ifr_map;
    #endif

    #ifdef HAVE_TXQUEUELEN
    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    ife->tx_queue_len = -1; /* unknown value */
    if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0)
    ife->tx_queue_len = ifr.ifr_qlen;
    #else
    ife->tx_queue_len = -1; /* unknown value */
    #endif

    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    ifr.ifr_addr.sa_family = AF_INET;
    memset(&ife->addr, 0, sizeof(struct sockaddr));
    if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) {
    ife->has_ip = 1;
    ife->addr = ifr.ifr_addr;
    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
    if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0)
    ife->dstaddr = ifr.ifr_dstaddr;

    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
    if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0)
    ife->broadaddr = ifr.ifr_broadaddr;

    strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
    memset(&ife->netmask, 0, sizeof(struct sockaddr));
    if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0)
    ife->netmask = ifr.ifr_netmask;
    }

    close(skfd);
    return 0;
    }
    用的是ioctl方法。
    下面是内核部分解析,解析SIOCGIFFLAGS的的调用过程

    ioctl(skfd, SIOCGIFFLAGS, &ifr)
    内核部分进入的函数是sock_ioctl,位于socket。

    static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
    {
    struct socket *sock;
    struct sock *sk;
    void __user *argp = (void __user *)arg;
    int pid, err;
    struct net *net;

    sock = file->private_data;
    sk = sock->sk;
    net = sock_net(sk);
    if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
    err = dev_ioctl(net, cmd, argp);
    } else
    #ifdef CONFIG_WEXT_CORE
    if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
    err = dev_ioctl(net, cmd, argp);
    } else
    #endif

    进入dev_ioctl函数

    int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
    {
    struct ifreq ifr;
    int ret;
    char *colon;

    /* One special case: SIOCGIFCONF takes ifconf argument
    and requires shared lock, because it sleeps writing
    to user space.
    */

    if (cmd == SIOCGIFCONF) {//ifconfig
    rtnl_lock();
    ret = dev_ifconf(net, (char __user *) arg);
    rtnl_unlock();
    return ret;
    }

    static int dev_ifconf(struct net *net, char __user *arg)
    {
    struct ifconf ifc;
    struct net_device *dev;
    char __user *pos;
    int len;
    int total;
    int i;

    /*
    * Fetch the caller's info block.
    */

    if (copy_from_user(&ifc, arg, sizeof(struct ifconf)))
    return -EFAULT;

    pos = ifc.ifc_buf;
    len = ifc.ifc_len;

    /*
    * Loop over the interfaces, and write an info block for each.
    */

    total = 0;
    for_each_netdev(net, dev) {
    for (i = 0; i < NPROTO; i++) {
    if (gifconf_list[i]) {//inet_gifconf
    int done;
    if (!pos)
    done = gifconf_list[i](dev, NULL, 0);
    else
    done = gifconf_list[i](dev, pos + total,
    len - total);
    if (done < 0)
    return -EFAULT;
    total += done;
    }
    }
    }

    遍历&(net)->dev_base_head链表上的net_device
    ————————————————
    版权声明:本文为CSDN博主「东升」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/liangdsing/java/article/details/70159314

    Always Believe Something Beauitful Will Be Happen
  • 相关阅读:
    配置.net 3.0开发环境
    SQL分页语句
    SQL注入的实现原理和防范
    asp.net页面缓存技术
    内网渗透基础
    内网渗透工作组信息收集
    ORA00702: bootstrap verison ” inconsistent with version ’8.0.0.0.0′
    我的新blog
    专业Oracle数据库恢复技术支持
    高等代数第2讲——n元线性方程组解的情况
  • 原文地址:https://www.cnblogs.com/Oude/p/12608336.html
Copyright © 2011-2022 走看看