1 /* 2 * Ioctl handler 3 * Linux ethernet bridge 4 * 5 * Authors: 6 * Lennert Buytenhek <buytenh@gnu.org> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 11 * 2 of the License, or (at your option) any later version. 12 */ 13 14 #include <linux/capability.h> 15 #include <linux/kernel.h> 16 #include <linux/if_bridge.h> 17 #include <linux/netdevice.h> 18 #include <linux/times.h> 19 #include <net/net_namespace.h> 20 #include <asm/uaccess.h> 21 #include "br_private.h" 22 23 /* called with RTNL */ 24 static int get_bridge_ifindices(int *indices, int num) 25 { 26 struct net_device *dev; 27 int i = 0; 28 29 for_each_netdev(&init_net, dev) { 30 if (i >= num) 31 break; 32 if (dev->priv_flags & IFF_EBRIDGE) 33 indices[i++] = dev->ifindex; 34 } 35 36 return i; 37 } 38 39 /* called with RTNL */ 40 static void get_port_ifindices(struct net_bridge *br, int *ifindices, int num) 41 { 42 struct net_bridge_port *p; 43 44 list_for_each_entry(p, &br->port_list, list) { 45 if (p->port_no < num) 46 ifindices[p->port_no] = p->dev->ifindex; 47 } 48 } 49 50 /* 51 * Format up to a page worth of forwarding table entries 52 * userbuf -- where to copy result 53 * maxnum -- maximum number of entries desired 54 * (limited to a page for sanity) 55 * offset -- number of records to skip 56 */ 57 static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, 58 unsigned long maxnum, unsigned long offset) 59 { 60 int num; 61 void *buf; 62 size_t size; 63 64 /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */ 65 if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry)) 66 maxnum = PAGE_SIZE/sizeof(struct __fdb_entry); 67 68 size = maxnum * sizeof(struct __fdb_entry); 69 70 buf = kmalloc(size, GFP_USER); 71 if (!buf) 72 return -ENOMEM; 73 74 num = br_fdb_fillbuf(br, buf, maxnum, offset); 75 if (num > 0) { 76 if (copy_to_user(userbuf, buf, num*sizeof(struct __fdb_entry))) 77 num = -EFAULT; 78 } 79 kfree(buf); 80 81 return num; 82 } 83 84 static int add_del_if(struct net_bridge *br, int ifindex, int isadd) 85 { 86 struct net_device *dev; 87 int ret; 88 89 if (!capable(CAP_NET_ADMIN)) 90 return -EPERM; 91 92 dev = dev_get_by_index(&init_net, ifindex); 93 if (dev == NULL) 94 return -EINVAL; 95 96 if (isadd) 97 ret = br_add_if(br, dev); 98 else 99 ret = br_del_if(br, dev); 100 101 dev_put(dev); 102 return ret; 103 } 104 105 /* 106 * Legacy ioctl's through SIOCDEVPRIVATE 107 * This interface is deprecated because it was too difficult to 108 * to do the translation for 32/64bit ioctl compatability. 109 */ 110 static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 111 { 112 struct net_bridge *br = netdev_priv(dev); 113 unsigned long args[4]; 114 115 if (copy_from_user(args, rq->ifr_data, sizeof(args))) 116 return -EFAULT; 117 118 switch (args[0]) { 119 case BRCTL_ADD_IF: 120 case BRCTL_DEL_IF: 121 return add_del_if(br, args[1], args[0] == BRCTL_ADD_IF); 122 123 case BRCTL_GET_BRIDGE_INFO: 124 { 125 struct __bridge_info b; 126 127 memset(&b, 0, sizeof(struct __bridge_info)); 128 rcu_read_lock(); 129 memcpy(&b.designated_root, &br->designated_root, 8); 130 memcpy(&b.bridge_id, &br->bridge_id, 8); 131 b.root_path_cost = br->root_path_cost; 132 b.max_age = jiffies_to_clock_t(br->max_age); 133 b.hello_time = jiffies_to_clock_t(br->hello_time); 134 b.forward_delay = br->forward_delay; 135 b.bridge_max_age = br->bridge_max_age; 136 b.bridge_hello_time = br->bridge_hello_time; 137 b.bridge_forward_delay = jiffies_to_clock_t(br->bridge_forward_delay); 138 b.topology_change = br->topology_change; 139 b.topology_change_detected = br->topology_change_detected; 140 b.root_port = br->root_port; 141 142 b.stp_enabled = (br->stp_enabled != BR_NO_STP); 143 b.ageing_time = jiffies_to_clock_t(br->ageing_time); 144 b.hello_timer_value = br_timer_value(&br->hello_timer); 145 b.tcn_timer_value = br_timer_value(&br->tcn_timer); 146 b.topology_change_timer_value = br_timer_value(&br->topology_change_timer); 147 b.gc_timer_value = br_timer_value(&br->gc_timer); 148 rcu_read_unlock(); 149 150 if (copy_to_user((void __user *)args[1], &b, sizeof(b))) 151 return -EFAULT; 152 153 return 0; 154 } 155 156 case BRCTL_GET_PORT_LIST: 157 { 158 int num, *indices; 159 160 num = args[2]; 161 if (num < 0) 162 return -EINVAL; 163 if (num == 0) 164 num = 256; 165 if (num > BR_MAX_PORTS) 166 num = BR_MAX_PORTS; 167 168 indices = kcalloc(num, sizeof(int), GFP_KERNEL); 169 if (indices == NULL) 170 return -ENOMEM; 171 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)) 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: 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: 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 memset(&p, 0, sizeof(struct __port_info)); 231 memcpy(&p.designated_root, &pt->designated_root, 8); 232 memcpy(&p.designated_bridge, &pt->designated_bridge, 8); 233 p.port_id = pt->port_id; 234 p.designated_port = pt->designated_port; 235 p.path_cost = pt->path_cost; 236 p.designated_cost = pt->designated_cost; 237 p.state = pt->state; 238 p.top_change_ack = pt->topology_change_ack; 239 p.config_pending = pt->config_pending; 240 p.message_age_timer_value = br_timer_value(&pt->message_age_timer); 241 p.forward_delay_timer_value = br_timer_value(&pt->forward_delay_timer); 242 p.hold_timer_value = br_timer_value(&pt->hold_timer); 243 244 rcu_read_unlock(); 245 246 if (copy_to_user((void __user *)args[1], &p, sizeof(p))) 247 return -EFAULT; 248 249 return 0; 250 } 251 252 case BRCTL_SET_BRIDGE_STP_STATE: 253 if (!capable(CAP_NET_ADMIN)) 254 return -EPERM; 255 256 br_stp_set_enabled(br, args[1]); 257 return 0; 258 259 case BRCTL_SET_BRIDGE_PRIORITY: 260 if (!capable(CAP_NET_ADMIN)) 261 return -EPERM; 262 263 spin_lock_bh(&br->lock); 264 br_stp_set_bridge_priority(br, args[1]); 265 spin_unlock_bh(&br->lock); 266 return 0; 267 268 case BRCTL_SET_PORT_PRIORITY: 269 { 270 struct net_bridge_port *p; 271 int ret = 0; 272 273 if (!capable(CAP_NET_ADMIN)) 274 return -EPERM; 275 276 if (args[2] >= (1<<(16-BR_PORT_BITS))) 277 return -ERANGE; 278 279 spin_lock_bh(&br->lock); 280 if ((p = br_get_port(br, args[1])) == NULL) 281 ret = -EINVAL; 282 else 283 br_stp_set_port_priority(p, args[2]); 284 spin_unlock_bh(&br->lock); 285 return ret; 286 } 287 288 case BRCTL_SET_PATH_COST: 289 { 290 struct net_bridge_port *p; 291 int ret = 0; 292 293 if (!capable(CAP_NET_ADMIN)) 294 return -EPERM; 295 296 if ((p = br_get_port(br, args[1])) == NULL) 297 ret = -EINVAL; 298 else 299 br_stp_set_path_cost(p, args[2]); 300 301 return ret; 302 } 303 304 case BRCTL_GET_FDB_ENTRIES: 305 return get_fdb_entries(br, (void __user *)args[1], 306 args[2], args[3]); 307 } 308 309 return -EOPNOTSUPP; 310 } 311 312 static int old_deviceless(void __user *uarg) 313 { 314 unsigned long args[3]; 315 316 if (copy_from_user(args, uarg, sizeof(args))) 317 return -EFAULT; 318 319 switch (args[0]) { 320 case BRCTL_GET_VERSION: 321 return BRCTL_VERSION; 322 323 case BRCTL_GET_BRIDGES: 324 { 325 int *indices; 326 int ret = 0; 327 328 if (args[2] >= 2048) 329 return -ENOMEM; 330 indices = kcalloc(args[2], sizeof(int), GFP_KERNEL); 331 if (indices == NULL) 332 return -ENOMEM; 333 334 args[2] = get_bridge_ifindices(indices, args[2]); 335 336 ret = copy_to_user((void __user *)args[1], indices, args[2]*sizeof(int)) 337 ? -EFAULT : args[2]; 338 339 kfree(indices); 340 return ret; 341 } 342 343 case BRCTL_ADD_BRIDGE: 344 case BRCTL_DEL_BRIDGE: 345 { 346 char buf[IFNAMSIZ]; 347 348 if (!capable(CAP_NET_ADMIN)) 349 return -EPERM; 350 351 if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ)) 352 return -EFAULT; 353 354 buf[IFNAMSIZ-1] = 0; 355 356 if (args[0] == BRCTL_ADD_BRIDGE) 357 return br_add_bridge(buf); 358 359 return br_del_bridge(buf); 360 } 361 } 362 363 return -EOPNOTSUPP; 364 } 365 366 int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg) 367 { 368 switch (cmd) { 369 case SIOCGIFBR: 370 case SIOCSIFBR: 371 return old_deviceless(uarg); 372 373 case SIOCBRADDBR: 374 case SIOCBRDELBR: 375 { 376 char buf[IFNAMSIZ]; 377 378 if (!capable(CAP_NET_ADMIN)) 379 return -EPERM; 380 381 if (copy_from_user(buf, uarg, IFNAMSIZ)) 382 return -EFAULT; 383 384 buf[IFNAMSIZ-1] = 0; 385 if (cmd == SIOCBRADDBR) 386 return br_add_bridge(buf); 387 388 return br_del_bridge(buf); 389 } 390 } 391 return -EOPNOTSUPP; 392 } 393 394 int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 395 { 396 struct net_bridge *br = netdev_priv(dev); 397 398 switch(cmd) { 399 case SIOCDEVPRIVATE: 400 return old_dev_ioctl(dev, rq, cmd); 401 402 case SIOCBRADDIF: 403 case SIOCBRDELIF: 404 return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF); 405 406 } 407 408 pr_debug("Bridge does not support ioctl 0x%x\n", cmd); 409 return -EOPNOTSUPP; 410 } 411