user space 通过SIOCSIFNAME修改网口的name

来源:互联网 发布:网络对人们生活的影响 编辑:程序博客网 时间:2024/06/05 09:00
上层udev可以通过SIOCSIFNAME来改变网口的name,这样通过ifconfig -a 或者 cat /proc/net/dev 就可以看打网口的name
路径在net/core/dev.c
static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
{
        case SIOCSIFNAME:
        ifr->ifr_newname[IFNAMSIZ-1] = '\0';
        return dev_change_name(dev, ifr->ifr_newname);

}
#if __UAPI_DEF_IF_IFNAMSIZ
#define    IFNAMSIZ    16
#endif /* __UAPI_DEF_IF_IFNAMSIZ */
#define    IFALIASZ    256
可以看到如果定义了__UAPI_DEF_IF_IFNAMSIZ的话,网口的name最多16个字符
dev_change_name->device_rename
int device_rename(struct device *dev, const char *new_name)
{
    struct kobject *kobj = &dev->kobj;
    char *old_device_name = NULL;
    int error;

    dev = get_device(dev);
    if (!dev)
        return -EINVAL;
// 如果debug的话,可以在dmesg中搜索renaming to 字段,就可以检测上层是否修改网口的名字
    dev_dbg(dev, "renaming to %s\n", new_name);
// 如果这个网口原本就没有name,就直接退出不用修改了
    old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
    if (!old_device_name) {
        error = -ENOMEM;
        goto out;
    }

    if (dev->class) {
        error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj,
                         kobj, old_device_name,
                         new_name, kobject_namespace(kobj));
        if (error)
            goto out;
    }
//最终的是在这里改名
    error = kobject_rename(kobj, new_name);
    if (error)
        goto out;

out:
    put_device(dev);

    kfree(old_device_name);

    return error;
}
int kobject_rename(struct kobject *kobj, const char *new_name)
{
    int error = 0;
    const char *devpath = NULL;
    const char *dup_name = NULL, *name;
    char *devpath_string = NULL;
    char *envp[2];

    kobj = kobject_get(kobj);
    if (!kobj)
        return -EINVAL;
    if (!kobj->parent)
        return -EINVAL;

    devpath = kobject_get_path(kobj, GFP_KERNEL);
    if (!devpath) {
        error = -ENOMEM;
        goto out;
    }
    devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
    if (!devpath_string) {
        error = -ENOMEM;
        goto out;
    }
    sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
    envp[0] = devpath_string;
    envp[1] = NULL;

    name = dup_name = kstrdup_const(new_name, GFP_KERNEL);
    if (!name) {
        error = -ENOMEM;
        goto out;
    }

    error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj));
    if (error)
        goto out;
// 最终在这改名,原来网口的名字最终体现在kobject 中的name 变量
    /* Install the new kobject name */
    dup_name = kobj->name;
    kobj->name = name;

    /* This function is mostly/only used for network interface.
     * Some hotplug package track interfaces by their name and
     * therefore want to know when the name is changed by the user. */
//同时上层改名成功,也可以cat 这个device的uevnet 看这个device发给上层的uenent 中是否包含改名的信息
    kobject_uevent_env(kobj, KOBJ_MOVE, envp);

out:
    kfree_const(dup_name);
    kfree(devpath_string);
    kfree(devpath);
    kobject_put(kobj);

    return error;
}

原创粉丝点击