br_ioctl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Ioctl handler
  3.  * Linux ethernet bridge
  4.  *
  5.  * Authors:
  6.  * Lennert Buytenhek <buytenh@gnu.org>
  7.  *
  8.  * $Id: br_ioctl.c,v 1.4 2000/11/08 05:16:40 davem Exp $
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License
  12.  * as published by the Free Software Foundation; either version
  13.  * 2 of the License, or (at your option) any later version.
  14.  */
  15. #include <linux/kernel.h>
  16. #include <linux/if_bridge.h>
  17. #include <linux/inetdevice.h>
  18. #include <asm/uaccess.h>
  19. #include "br_private.h"
  20. static int br_ioctl_device(struct net_bridge *br,
  21.    unsigned int cmd,
  22.    unsigned long arg0,
  23.    unsigned long arg1,
  24.    unsigned long arg2)
  25. {
  26. if (br == NULL)
  27. return -EINVAL;
  28. switch (cmd)
  29. {
  30. case BRCTL_ADD_IF:
  31. case BRCTL_DEL_IF:
  32. {
  33. struct net_device *dev;
  34. int ret;
  35. dev = dev_get_by_index(arg0);
  36. if (dev == NULL)
  37. return -EINVAL;
  38. if (cmd == BRCTL_ADD_IF)
  39. ret = br_add_if(br, dev);
  40. else
  41. ret = br_del_if(br, dev);
  42. dev_put(dev);
  43. return ret;
  44. }
  45. case BRCTL_GET_BRIDGE_INFO:
  46. {
  47. struct __bridge_info b;
  48. memset(&b, 0, sizeof(struct __bridge_info));
  49. memcpy(&b.designated_root, &br->designated_root, 8);
  50. memcpy(&b.bridge_id, &br->bridge_id, 8);
  51. b.root_path_cost = br->root_path_cost;
  52. b.max_age = br->max_age;
  53. b.hello_time = br->hello_time;
  54. b.forward_delay = br->forward_delay;
  55. b.bridge_max_age = br->bridge_max_age;
  56. b.bridge_hello_time = br->bridge_hello_time;
  57. b.bridge_forward_delay = br->bridge_forward_delay;
  58. b.topology_change = br->topology_change;
  59. b.topology_change_detected = br->topology_change_detected;
  60. b.root_port = br->root_port;
  61. b.stp_enabled = br->stp_enabled;
  62. b.ageing_time = br->ageing_time;
  63. b.gc_interval = br->gc_interval;
  64. b.hello_timer_value = br_timer_get_residue(&br->hello_timer);
  65. b.tcn_timer_value = br_timer_get_residue(&br->tcn_timer);
  66. b.topology_change_timer_value = br_timer_get_residue(&br->topology_change_timer);
  67. b.gc_timer_value = br_timer_get_residue(&br->gc_timer);
  68. if (copy_to_user((void *)arg0, &b, sizeof(b)))
  69. return -EFAULT;
  70. return 0;
  71. }
  72. case BRCTL_GET_PORT_LIST:
  73. {
  74. int i;
  75. int indices[256];
  76. for (i=0;i<256;i++)
  77. indices[i] = 0;
  78. br_get_port_ifindices(br, indices);
  79. if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
  80. return -EFAULT;
  81. return 0;
  82. }
  83. case BRCTL_SET_BRIDGE_FORWARD_DELAY:
  84. br->bridge_forward_delay = arg0;
  85. if (br_is_root_bridge(br))
  86. br->forward_delay = arg0;
  87. return 0;
  88. case BRCTL_SET_BRIDGE_HELLO_TIME:
  89. br->bridge_hello_time = arg0;
  90. if (br_is_root_bridge(br))
  91. br->hello_time = arg0;
  92. return 0;
  93. case BRCTL_SET_BRIDGE_MAX_AGE:
  94. br->bridge_max_age = arg0;
  95. if (br_is_root_bridge(br))
  96. br->max_age = arg0;
  97. return 0;
  98. case BRCTL_SET_AGEING_TIME:
  99. br->ageing_time = arg0;
  100. return 0;
  101. case BRCTL_SET_GC_INTERVAL:
  102. br->gc_interval = arg0;
  103. return 0;
  104. case BRCTL_GET_PORT_INFO:
  105. {
  106. struct __port_info p;
  107. struct net_bridge_port *pt;
  108. if ((pt = br_get_port(br, arg1)) == NULL)
  109. return -EINVAL;
  110. memset(&p, 0, sizeof(struct __port_info));
  111. memcpy(&p.designated_root, &pt->designated_root, 8);
  112. memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
  113. p.port_id = pt->port_id;
  114. p.designated_port = pt->designated_port;
  115. p.path_cost = pt->path_cost;
  116. p.designated_cost = pt->designated_cost;
  117. p.state = pt->state;
  118. p.top_change_ack = pt->topology_change_ack;
  119. p.config_pending = pt->config_pending;
  120. p.message_age_timer_value = br_timer_get_residue(&pt->message_age_timer);
  121. p.forward_delay_timer_value = br_timer_get_residue(&pt->forward_delay_timer);
  122. p.hold_timer_value = br_timer_get_residue(&pt->hold_timer);
  123. if (copy_to_user((void *)arg0, &p, sizeof(p)))
  124. return -EFAULT;
  125. return 0;
  126. }
  127. case BRCTL_SET_BRIDGE_STP_STATE:
  128. br->stp_enabled = arg0?1:0;
  129. return 0;
  130. case BRCTL_SET_BRIDGE_PRIORITY:
  131. br_stp_set_bridge_priority(br, arg0);
  132. return 0;
  133. case BRCTL_SET_PORT_PRIORITY:
  134. {
  135. struct net_bridge_port *p;
  136. if ((p = br_get_port(br, arg0)) == NULL)
  137. return -EINVAL;
  138. br_stp_set_port_priority(p, arg1);
  139. return 0;
  140. }
  141. case BRCTL_SET_PATH_COST:
  142. {
  143. struct net_bridge_port *p;
  144. if ((p = br_get_port(br, arg0)) == NULL)
  145. return -EINVAL;
  146. br_stp_set_path_cost(p, arg1);
  147. return 0;
  148. }
  149. case BRCTL_GET_FDB_ENTRIES:
  150. return br_fdb_get_entries(br, (void *)arg0, arg1, arg2);
  151. }
  152. return -EOPNOTSUPP;
  153. }
  154. static int br_ioctl_deviceless(unsigned int cmd,
  155.        unsigned long arg0,
  156.        unsigned long arg1)
  157. {
  158. switch (cmd)
  159. {
  160. case BRCTL_GET_VERSION:
  161. return BRCTL_VERSION;
  162. case BRCTL_GET_BRIDGES:
  163. {
  164. int i;
  165. int indices[64];
  166. for (i=0;i<64;i++)
  167. indices[i] = 0;
  168. if (arg1 > 64)
  169. arg1 = 64;
  170. arg1 = br_get_bridge_ifindices(indices, arg1);
  171. if (copy_to_user((void *)arg0, indices, arg1*sizeof(int)))
  172. return -EFAULT;
  173. return arg1;
  174. }
  175. case BRCTL_ADD_BRIDGE:
  176. case BRCTL_DEL_BRIDGE:
  177. {
  178. char buf[IFNAMSIZ];
  179. if (copy_from_user(buf, (void *)arg0, IFNAMSIZ))
  180. return -EFAULT;
  181. buf[IFNAMSIZ-1] = 0;
  182. if (cmd == BRCTL_ADD_BRIDGE)
  183. return br_add_bridge(buf);
  184. return br_del_bridge(buf);
  185. }
  186. }
  187. return -EOPNOTSUPP;
  188. }
  189. DECLARE_MUTEX(ioctl_mutex);
  190. int br_ioctl_deviceless_stub(unsigned long arg)
  191. {
  192. int err;
  193. unsigned long i[3];
  194. if (!capable(CAP_NET_ADMIN))
  195. return -EPERM;
  196. if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long)))
  197. return -EFAULT;
  198. down(&ioctl_mutex);
  199. err = br_ioctl_deviceless(i[0], i[1], i[2]);
  200. up(&ioctl_mutex);
  201. return err;
  202. }
  203. int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2)
  204. {
  205. int err;
  206. if (!capable(CAP_NET_ADMIN))
  207. return -EPERM;
  208. down(&ioctl_mutex);
  209. err = br_ioctl_deviceless(cmd, arg0, arg1);
  210. if (err == -EOPNOTSUPP)
  211. err = br_ioctl_device(br, cmd, arg0, arg1, arg2);
  212. up(&ioctl_mutex);
  213. return err;
  214. }
  215. void br_call_ioctl_atomic(void (*fn)(void))
  216. {
  217. down(&ioctl_mutex);
  218. fn();
  219. up(&ioctl_mutex);
  220. }