Chinaunix首页 | 论坛 | 博客
  • 博客访问: 819755
  • 博文数量: 264
  • 博客积分: 592
  • 博客等级: 中士
  • 技术积分: 1574
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-24 22:02
文章分类

全部博文(264)

文章存档

2019年(2)

2018年(1)

2017年(1)

2016年(4)

2015年(14)

2014年(57)

2013年(88)

2012年(97)

分类: LINUX

2014-02-12 15:19:53

转:http://blog.csdn.net/nerdx/article/details/12223489
  1. //  1.网桥子系统向用户空间提供的接口:  
  2. //      1.1 通过socket ioctl创建网桥  
  3. //      1.2 通过网桥的特殊设备文件ioctl添加网桥端口  
  4.   
  5. //  桥接在socket ioctl中的衔接处理  
  6. //  处理的命令类型:  
  7. //      1.获取网桥信息  
  8. //      2.设置网桥信息  
  9. //      3.添加网桥  
  10. //      4.删除网桥  
  11. 1.1 static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)  
  12. {  
  13.         ...  
  14.         case SIOCGIFBR:  
  15.         case SIOCSIFBR:  
  16.         case SIOCBRADDBR:  
  17.         case SIOCBRDELBR:  
  18.             err = -ENOPKG;  
  19.             if (!br_ioctl_hook)//如果钩子函数没有被设置,则加载桥接模块  
  20.                 request_module("bridge");  
  21.   
  22.             down(&br_ioctl_mutex);//在执行钩子函数的过程中,获取信号量,防止在钩子函数被执行的过程,被设置  
  23.             if (br_ioctl_hook)   
  24.                 err = br_ioctl_hook(cmd, argp);  
  25.             up(&br_ioctl_mutex);  
  26.             break;  
  27.         ...  
  28. }  
  29. //  网桥的socket ioctl  
  30. //      在网桥子系统初始化时,由brioctl_set设置br_ioctl_hook = br_ioctl_deviceless_stub  
  31. //  调用路径: sock_ioctl->br_ioctl_hook  
  32. 1.2 int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)  
  33. {  
  34.     switch (cmd) {  
  35.     case SIOCGIFBR:  
  36.     case SIOCSIFBR:  
  37.         return old_deviceless(uarg);//老式网桥命令  
  38.           
  39.     case SIOCBRADDBR://新网桥命令,添加或删除网桥  
  40.     case SIOCBRDELBR:  
  41.     {  
  42.         char buf[IFNAMSIZ];  
  43.   
  44.         if (!capable(CAP_NET_ADMIN))//当前进程需要admin权限  
  45.             return -EPERM;  
  46.   
  47.         if (copy_from_user(buf, uarg, IFNAMSIZ))//uarg提供网桥名字  
  48.             return -EFAULT;  
  49.   
  50.         buf[IFNAMSIZ-1] = 0;//c格式字符串  
  51.         if (cmd == SIOCBRADDBR)//添加网桥  
  52.             return br_add_bridge(buf);  
  53.   
  54.         return br_del_bridge(buf);//删除  
  55.     }  
  56.     }  
  57.     return -EOPNOTSUPP;  
  58. }  
  59.   
  60. //  网桥老式ioctl命令处理  
  61. //      处理的命令类型为SIOCGIFBR, SIOCSIFBR  
  62. //  调用路径:br_ioctl_deviceless_stub->old_deviceless  
  63. 1.3 static int old_deviceless(void __user *uarg)  
  64. {  
  65.     unsigned long args[3];  
  66.   
  67.     if (copy_from_user(args, uarg, sizeof(args)))//从用户空间拷贝参数  
  68.         return -EFAULT;  
  69.   
  70.     switch (args[0]) {//由uarg[0]提供命令  
  71.     case BRCTL_GET_VERSION://获取网桥版本  
  72.         return BRCTL_VERSION;  
  73.   
  74.     case BRCTL_GET_BRIDGES://获取网桥接口的index  
  75.     {  
  76.         int *indices;  
  77.         int ret = 0;  
  78.   
  79.         indices = kmalloc(args[2]*sizeof(int), GFP_KERNEL);//uarg[2]指示获取接口数  
  80.         if (indices == NULL)  
  81.             return -ENOMEM;  
  82.   
  83.         memset(indices, 0, args[2]*sizeof(int));  
  84.         args[2] = get_bridge_ifindices(indices, args[2]);//实际获取到的接口数  
  85.   
  86.         ret = copy_to_user((void __user *)args[1], indices, args[2]*sizeof(int))//uarg[1]包含保存返回值的位置  
  87.             ? -EFAULT : args[2];  
  88.   
  89.         kfree(indices);  
  90.         return ret;  
  91.     }  
  92.   
  93.     case BRCTL_ADD_BRIDGE://添加或删除网桥,网桥名主机内唯一  
  94.     case BRCTL_DEL_BRIDGE:  
  95.     {  
  96.         char buf[IFNAMSIZ];  
  97.   
  98.         if (!capable(CAP_NET_ADMIN))//当前进程admin权限  
  99.             return -EPERM;  
  100.   
  101.         if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ))//uarg[1]保存网桥名的内存地址  
  102.             return -EFAULT;  
  103.   
  104.         buf[IFNAMSIZ-1] = 0;//c风格字符串  
  105.   
  106.         if (args[0] == BRCTL_ADD_BRIDGE)  
  107.             return br_add_bridge(buf);//添加网桥  
  108.   
  109.         return br_del_bridge(buf);//删除网桥  
  110.     }  
  111.     }  
  112.   
  113.     return -EOPNOTSUPP;  
  114. }  
  115.   
  116. //  网桥的特殊设备文件ioctl处理  
  117. //      通过打开网桥设备文件,ioctl  
  118. //  处理的命令:  
  119. //      1.老式网桥命令  
  120. //      2.新式添加删除网桥端口命令  
  121. 2.1 int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  
  122. {  
  123.     struct net_bridge *br = netdev_priv(dev);  
  124.   
  125.     switch(cmd) {  
  126.     case SIOCDEVPRIVATE://老式命令  
  127.         return old_dev_ioctl(dev, rq, cmd);  
  128.   
  129.     case SIOCBRADDIF://添加删除接口  
  130.     case SIOCBRDELIF:  
  131.         return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF);  
  132.   
  133.     }  
  134.   
  135.     pr_debug("Bridge does not support ioctl 0x%x\n", cmd);  
  136.     return -EOPNOTSUPP;  
  137. }  
  138.   
  139. //  遗留的老式设备文件ioctl  
  140. //      通过cmd=SIOCDEVPRIVATE调用  
  141. //  调用路径:br_dev_ioctl->old_dev_ioctl  
  142. 2.2 static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  
  143. {  
  144.     struct net_bridge *br = netdev_priv(dev);  
  145.     unsigned long args[4];  
  146.       
  147.     if (copy_from_user(args, rq->ifr_data, sizeof(args)))  
  148.         return -EFAULT;  
  149.   
  150.     switch (args[0]) {//删除添加接口  
  151.     case BRCTL_ADD_IF:  
  152.     case BRCTL_DEL_IF:  
  153.         return add_del_if(br, args[1], args[0] == BRCTL_ADD_IF);  
  154.   
  155.     case BRCTL_GET_BRIDGE_INFO:  
  156.     {  
  157.         struct __bridge_info b;  
  158.         //获取网桥设备信息  
  159.         ...  
  160.   
  161.         if (copy_to_user((void __user *)args[1], &b, sizeof(b)))  
  162.             return -EFAULT;  
  163.   
  164.         return 0;  
  165.     }  
  166.   
  167.     case BRCTL_GET_PORT_LIST://获取网桥端口链表  
  168.     {  
  169.         int num, *indices;  
  170.         ...  
  171.         //返回网桥端口的index  
  172.         get_port_ifindices(br, indices, num);  
  173.         if (copy_to_user((void __user *)args[1], indices, num*sizeof(int)))  
  174.             num =  -EFAULT;  
  175.         kfree(indices);  
  176.         return num;  
  177.     }  
  178.   
  179.     case BRCTL_SET_BRIDGE_FORWARD_DELAY://设置状态转移时间间隔  
  180.         if (!capable(CAP_NET_ADMIN))//当前进程需要admin权限  
  181.             return -EPERM;  
  182.   
  183.         spin_lock_bh(&br->lock);  
  184.         br->bridge_forward_delay = clock_t_to_jiffies(args[1]);  
  185.         if (br_is_root_bridge(br))  
  186.             br->forward_delay = br->bridge_forward_delay;  
  187.         spin_unlock_bh(&br->lock);  
  188.         return 0;  
  189.   
  190.     case BRCTL_SET_BRIDGE_HELLO_TIME://设置hello时间间隔  
  191.         if (!capable(CAP_NET_ADMIN))  
  192.             return -EPERM;  
  193.   
  194.         spin_lock_bh(&br->lock);  
  195.         br->bridge_hello_time = clock_t_to_jiffies(args[1]);  
  196.         if (br_is_root_bridge(br))  
  197.             br->hello_time = br->bridge_hello_time;  
  198.         spin_unlock_bh(&br->lock);  
  199.         return 0;  
  200.   
  201.     case BRCTL_SET_BRIDGE_MAX_AGE://BPDU信息的生存期  
  202.         if (!capable(CAP_NET_ADMIN))  
  203.             return -EPERM;  
  204.   
  205.         spin_lock_bh(&br->lock);  
  206.         br->bridge_max_age = clock_t_to_jiffies(args[1]);  
  207.         if (br_is_root_bridge(br))  
  208.             br->max_age = br->bridge_max_age;  
  209.         spin_unlock_bh(&br->lock);  
  210.         return 0;  
  211.   
  212.     case BRCTL_SET_AGEING_TIME://转发项的老化时间  
  213.         if (!capable(CAP_NET_ADMIN))  
  214.             return -EPERM;  
  215.   
  216.         br->ageing_time = clock_t_to_jiffies(args[1]);  
  217.         return 0;  
  218.   
  219.     case BRCTL_GET_PORT_INFO://端口信息  
  220.     {  
  221.         struct __port_info p;  
  222.         struct net_bridge_port *pt;  
  223.   
  224.         rcu_read_lock();  
  225.         if ((pt = br_get_port(br, args[2])) == NULL) {  
  226.             rcu_read_unlock();  
  227.             return -EINVAL;  
  228.         }  
  229.         ....  
  230.         rcu_read_unlock();  
  231.   
  232.         if (copy_to_user((void __user *)args[1], &p, sizeof(p)))  
  233.             return -EFAULT;  
  234.   
  235.         return 0;  
  236.     }  
  237.   
  238.     case BRCTL_SET_BRIDGE_STP_STATE://启动或关闭stp  
  239.         if (!capable(CAP_NET_ADMIN))  
  240.             return -EPERM;  
  241.   
  242.         br->stp_enabled = args[1]?1:0;  
  243.         return 0;  
  244.   
  245.     case BRCTL_SET_BRIDGE_PRIORITY://设置网桥的优先级  
  246.         if (!capable(CAP_NET_ADMIN))  
  247.             return -EPERM;  
  248.   
  249.         spin_lock_bh(&br->lock);  
  250.         br_stp_set_bridge_priority(br, args[1]);  
  251.         spin_unlock_bh(&br->lock);  
  252.         return 0;  
  253.   
  254.     case BRCTL_SET_PORT_PRIORITY://设置端口的优先级  
  255.     {  
  256.         struct net_bridge_port *p;  
  257.         int ret = 0;  
  258.   
  259.         if (!capable(CAP_NET_ADMIN))  
  260.             return -EPERM;  
  261.   
  262.         if (args[2] >= (1<<(16-BR_PORT_BITS)))//2字节中,端口号使用的位数  
  263.             return -ERANGE;  
  264.   
  265.         spin_lock_bh(&br->lock);  
  266.         if ((p = br_get_port(br, args[1])) == NULL)   
  267.             ret = -EINVAL;  
  268.         else  
  269.             br_stp_set_port_priority(p, args[2]);  
  270.         spin_unlock_bh(&br->lock);  
  271.         return ret;  
  272.     }  
  273.   
  274.     case BRCTL_SET_PATH_COST://设置路径开销  
  275.     {  
  276.         struct net_bridge_port *p;  
  277.         int ret = 0;  
  278.   
  279.         if (!capable(CAP_NET_ADMIN))  
  280.             return -EPERM;  
  281.   
  282.         spin_lock_bh(&br->lock);  
  283.         if ((p = br_get_port(br, args[1])) == NULL)  
  284.             ret = -EINVAL;  
  285.         else  
  286.             br_stp_set_path_cost(p, args[2]);  
  287.         spin_unlock_bh(&br->lock);  
  288.         return ret;  
  289.     }  
  290.   
  291.     case BRCTL_GET_FDB_ENTRIES://获取转发项的个数  
  292.         return get_fdb_entries(br, (void __user *)args[1],   
  293.                        args[2], args[3]);  
  294.     }  
  295.   
  296.     return -EOPNOTSUPP;  
  297. }  
阅读(711) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~