linux-old/net/bridge/br_ioctl.c
<<
>>
Prefs
   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
  16#include <linux/kernel.h>
  17#include <linux/if_bridge.h>
  18#include <linux/inetdevice.h>
  19#include <asm/uaccess.h>
  20#include "br_private.h"
  21
  22static int br_ioctl_device(struct net_bridge *br,
  23                           unsigned int cmd,
  24                           unsigned long arg0,
  25                           unsigned long arg1,
  26                           unsigned long arg2)
  27{
  28        if (br == NULL)
  29                return -EINVAL;
  30
  31        switch (cmd)
  32        {
  33        case BRCTL_ADD_IF:
  34        case BRCTL_DEL_IF:
  35        {
  36                struct net_device *dev;
  37                int ret;
  38
  39                dev = dev_get_by_index(arg0);
  40                if (dev == NULL)
  41                        return -EINVAL;
  42
  43                if (cmd == BRCTL_ADD_IF)
  44                        ret = br_add_if(br, dev);
  45                else
  46                        ret = br_del_if(br, dev);
  47
  48                dev_put(dev);
  49                return ret;
  50        }
  51
  52        case BRCTL_GET_BRIDGE_INFO:
  53        {
  54                struct __bridge_info b;
  55
  56                memset(&b, 0, sizeof(struct __bridge_info));
  57                memcpy(&b.designated_root, &br->designated_root, 8);
  58                memcpy(&b.bridge_id, &br->bridge_id, 8);
  59                b.root_path_cost = br->root_path_cost;
  60                b.max_age = br->max_age;
  61                b.hello_time = br->hello_time;
  62                b.forward_delay = br->forward_delay;
  63                b.bridge_max_age = br->bridge_max_age;
  64                b.bridge_hello_time = br->bridge_hello_time;
  65                b.bridge_forward_delay = br->bridge_forward_delay;
  66                b.topology_change = br->topology_change;
  67                b.topology_change_detected = br->topology_change_detected;
  68                b.root_port = br->root_port;
  69                b.stp_enabled = br->stp_enabled;
  70                b.ageing_time = br->ageing_time;
  71                b.gc_interval = br->gc_interval;
  72                b.hello_timer_value = br_timer_get_residue(&br->hello_timer);
  73                b.tcn_timer_value = br_timer_get_residue(&br->tcn_timer);
  74                b.topology_change_timer_value = br_timer_get_residue(&br->topology_change_timer);
  75                b.gc_timer_value = br_timer_get_residue(&br->gc_timer);
  76
  77                if (copy_to_user((void *)arg0, &b, sizeof(b)))
  78                        return -EFAULT;
  79
  80                return 0;
  81        }
  82
  83        case BRCTL_GET_PORT_LIST:
  84        {
  85                int i;
  86                int indices[256];
  87
  88                for (i=0;i<256;i++)
  89                        indices[i] = 0;
  90
  91                br_get_port_ifindices(br, indices);
  92                if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
  93                        return -EFAULT;
  94
  95                return 0;
  96        }
  97
  98        case BRCTL_SET_BRIDGE_FORWARD_DELAY:
  99                br->bridge_forward_delay = arg0;
 100                if (br_is_root_bridge(br))
 101                        br->forward_delay = arg0;
 102                return 0;
 103
 104        case BRCTL_SET_BRIDGE_HELLO_TIME:
 105                br->bridge_hello_time = arg0;
 106                if (br_is_root_bridge(br))
 107                        br->hello_time = arg0;
 108                return 0;
 109
 110        case BRCTL_SET_BRIDGE_MAX_AGE:
 111                br->bridge_max_age = arg0;
 112                if (br_is_root_bridge(br))
 113                        br->max_age = arg0;
 114                return 0;
 115
 116        case BRCTL_SET_AGEING_TIME:
 117                br->ageing_time = arg0;
 118                return 0;
 119
 120        case BRCTL_SET_GC_INTERVAL:
 121                br->gc_interval = arg0;
 122                return 0;
 123
 124        case BRCTL_GET_PORT_INFO:
 125        {
 126                struct __port_info p;
 127                struct net_bridge_port *pt;
 128
 129                if ((pt = br_get_port(br, arg1)) == NULL)
 130                        return -EINVAL;
 131
 132                memset(&p, 0, sizeof(struct __port_info));
 133                memcpy(&p.designated_root, &pt->designated_root, 8);
 134                memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
 135                p.port_id = pt->port_id;
 136                p.designated_port = pt->designated_port;
 137                p.path_cost = pt->path_cost;
 138                p.designated_cost = pt->designated_cost;
 139                p.state = pt->state;
 140                p.top_change_ack = pt->topology_change_ack;
 141                p.config_pending = pt->config_pending;
 142                p.message_age_timer_value = br_timer_get_residue(&pt->message_age_timer);
 143                p.forward_delay_timer_value = br_timer_get_residue(&pt->forward_delay_timer);
 144                p.hold_timer_value = br_timer_get_residue(&pt->hold_timer);
 145
 146                if (copy_to_user((void *)arg0, &p, sizeof(p)))
 147                        return -EFAULT;
 148
 149                return 0;
 150        }
 151
 152        case BRCTL_SET_BRIDGE_STP_STATE:
 153                br->stp_enabled = arg0?1:0;
 154                return 0;
 155
 156        case BRCTL_SET_BRIDGE_PRIORITY:
 157                br_stp_set_bridge_priority(br, arg0);
 158                return 0;
 159
 160        case BRCTL_SET_PORT_PRIORITY:
 161        {
 162                struct net_bridge_port *p;
 163
 164                if ((p = br_get_port(br, arg0)) == NULL)
 165                        return -EINVAL;
 166                br_stp_set_port_priority(p, arg1);
 167                return 0;
 168        }
 169
 170        case BRCTL_SET_PATH_COST:
 171        {
 172                struct net_bridge_port *p;
 173
 174                if ((p = br_get_port(br, arg0)) == NULL)
 175                        return -EINVAL;
 176                br_stp_set_path_cost(p, arg1);
 177                return 0;
 178        }
 179
 180        case BRCTL_GET_FDB_ENTRIES:
 181                return br_fdb_get_entries(br, (void *)arg0, arg1, arg2);
 182        }
 183
 184        return -EOPNOTSUPP;
 185}
 186
 187static int br_ioctl_deviceless(unsigned int cmd,
 188                               unsigned long arg0,
 189                               unsigned long arg1)
 190{
 191        switch (cmd)
 192        {
 193        case BRCTL_GET_VERSION:
 194                return BRCTL_VERSION;
 195
 196        case BRCTL_GET_BRIDGES:
 197        {
 198                int i;
 199                int indices[64];
 200
 201                for (i=0;i<64;i++)
 202                        indices[i] = 0;
 203
 204                if (arg1 > 64)
 205                        arg1 = 64;
 206                arg1 = br_get_bridge_ifindices(indices, arg1);
 207                if (copy_to_user((void *)arg0, indices, arg1*sizeof(int)))
 208                        return -EFAULT;
 209
 210                return arg1;
 211        }
 212
 213        case BRCTL_ADD_BRIDGE:
 214        case BRCTL_DEL_BRIDGE:
 215        {
 216                char buf[IFNAMSIZ];
 217
 218                if (copy_from_user(buf, (void *)arg0, IFNAMSIZ))
 219                        return -EFAULT;
 220
 221                buf[IFNAMSIZ-1] = 0;
 222
 223                if (cmd == BRCTL_ADD_BRIDGE)
 224                        return br_add_bridge(buf);
 225
 226                return br_del_bridge(buf);
 227        }
 228        }
 229
 230        return -EOPNOTSUPP;
 231}
 232
 233static DECLARE_MUTEX(ioctl_mutex);
 234
 235int br_ioctl_deviceless_stub(unsigned long arg)
 236{
 237        int err;
 238        unsigned long i[3];
 239
 240        if (!capable(CAP_NET_ADMIN))
 241                return -EPERM;
 242
 243        if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long)))
 244                return -EFAULT;
 245
 246        down(&ioctl_mutex);
 247        err = br_ioctl_deviceless(i[0], i[1], i[2]);
 248        up(&ioctl_mutex);
 249
 250        return err;
 251}
 252
 253int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2)
 254{
 255        int err;
 256
 257        if (!capable(CAP_NET_ADMIN))
 258                return -EPERM;
 259
 260        down(&ioctl_mutex);
 261        err = br_ioctl_deviceless(cmd, arg0, arg1);
 262        if (err == -EOPNOTSUPP)
 263                err = br_ioctl_device(br, cmd, arg0, arg1, arg2);
 264        up(&ioctl_mutex);
 265
 266        return err;
 267}
 268
 269void br_call_ioctl_atomic(void (*fn)(void))
 270{
 271        down(&ioctl_mutex);
 272        fn();
 273        up(&ioctl_mutex);
 274}
 275
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.