linux/net/atm/ioctl.c
<<
>>
Prefs
   1/* ATM ioctl handling */
   2
   3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
   4/* 2003 John Levon  <levon@movementarian.org> */
   5
   6
   7#include <linux/module.h>
   8#include <linux/kmod.h>
   9#include <linux/net.h>          /* struct socket, struct proto_ops */
  10#include <linux/atm.h>          /* ATM stuff */
  11#include <linux/atmdev.h>
  12#include <linux/atmclip.h>      /* CLIP_*ENCAP */
  13#include <linux/atmarp.h>       /* manifest constants */
  14#include <linux/capability.h>
  15#include <linux/sonet.h>        /* for ioctls */
  16#include <linux/atmsvc.h>
  17#include <linux/atmmpc.h>
  18#include <net/atmclip.h>
  19#include <linux/atmlec.h>
  20#include <linux/mutex.h>
  21#include <asm/ioctls.h>
  22#include <net/compat.h>
  23
  24#include "resources.h"
  25#include "signaling.h"          /* for WAITING and sigd_attach */
  26#include "common.h"
  27
  28
  29static DEFINE_MUTEX(ioctl_mutex);
  30static LIST_HEAD(ioctl_list);
  31
  32
  33void register_atm_ioctl(struct atm_ioctl *ioctl)
  34{
  35        mutex_lock(&ioctl_mutex);
  36        list_add_tail(&ioctl->list, &ioctl_list);
  37        mutex_unlock(&ioctl_mutex);
  38}
  39
  40void deregister_atm_ioctl(struct atm_ioctl *ioctl)
  41{
  42        mutex_lock(&ioctl_mutex);
  43        list_del(&ioctl->list);
  44        mutex_unlock(&ioctl_mutex);
  45}
  46
  47EXPORT_SYMBOL(register_atm_ioctl);
  48EXPORT_SYMBOL(deregister_atm_ioctl);
  49
  50static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg, int compat)
  51{
  52        struct sock *sk = sock->sk;
  53        struct atm_vcc *vcc;
  54        int error;
  55        struct list_head * pos;
  56        void __user *argp = (void __user *)arg;
  57
  58        vcc = ATM_SD(sock);
  59        switch (cmd) {
  60                case SIOCOUTQ:
  61                        if (sock->state != SS_CONNECTED ||
  62                            !test_bit(ATM_VF_READY, &vcc->flags)) {
  63                                error =  -EINVAL;
  64                                goto done;
  65                        }
  66                        error = put_user(sk->sk_sndbuf -
  67                                         atomic_read(&sk->sk_wmem_alloc),
  68                                         (int __user *) argp) ? -EFAULT : 0;
  69                        goto done;
  70                case SIOCINQ:
  71                        {
  72                                struct sk_buff *skb;
  73
  74                                if (sock->state != SS_CONNECTED) {
  75                                        error = -EINVAL;
  76                                        goto done;
  77                                }
  78                                skb = skb_peek(&sk->sk_receive_queue);
  79                                error = put_user(skb ? skb->len : 0,
  80                                                 (int __user *)argp) ? -EFAULT : 0;
  81                                goto done;
  82                        }
  83                case SIOCGSTAMP: /* borrowed from IP */
  84#ifdef CONFIG_COMPAT
  85                        if (compat)
  86                                error = compat_sock_get_timestamp(sk, argp);
  87                        else
  88#endif
  89                                error = sock_get_timestamp(sk, argp);
  90                        goto done;
  91                case SIOCGSTAMPNS: /* borrowed from IP */
  92#ifdef CONFIG_COMPAT
  93                        if (compat)
  94                                error = compat_sock_get_timestampns(sk, argp);
  95                        else
  96#endif
  97                                error = sock_get_timestampns(sk, argp);
  98                        goto done;
  99                case ATM_SETSC:
 100                        if (net_ratelimit())
 101                                printk(KERN_WARNING "ATM_SETSC is obsolete; used by %s:%d\n",
 102                                       current->comm, task_pid_nr(current));
 103                        error = 0;
 104                        goto done;
 105                case ATMSIGD_CTRL:
 106                        if (!capable(CAP_NET_ADMIN)) {
 107                                error = -EPERM;
 108                                goto done;
 109                        }
 110                        /*
 111                         * The user/kernel protocol for exchanging signalling
 112                         * info uses kernel pointers as opaque references,
 113                         * so the holder of the file descriptor can scribble
 114                         * on the kernel... so we should make sure that we
 115                         * have the same privileges that /proc/kcore needs
 116                         */
 117                        if (!capable(CAP_SYS_RAWIO)) {
 118                                error = -EPERM;
 119                                goto done;
 120                        }
 121#ifdef CONFIG_COMPAT
 122                        /* WTF? I don't even want to _think_ about making this
 123                           work for 32-bit userspace. TBH I don't really want
 124                           to think about it at all. dwmw2. */
 125                        if (compat) {
 126                                if (net_ratelimit())
 127                                        printk(KERN_WARNING "32-bit task cannot be atmsigd\n");
 128                                error = -EINVAL;
 129                                goto done;
 130                        }
 131#endif
 132                        error = sigd_attach(vcc);
 133                        if (!error)
 134                                sock->state = SS_CONNECTED;
 135                        goto done;
 136                case ATM_SETBACKEND:
 137                case ATM_NEWBACKENDIF:
 138                        {
 139                                atm_backend_t backend;
 140                                error = get_user(backend, (atm_backend_t __user *) argp);
 141                                if (error)
 142                                        goto done;
 143                                switch (backend) {
 144                                        case ATM_BACKEND_PPP:
 145                                                request_module("pppoatm");
 146                                                break;
 147                                        case ATM_BACKEND_BR2684:
 148                                                request_module("br2684");
 149                                                break;
 150                                }
 151                        }
 152                        break;
 153                case ATMMPC_CTRL:
 154                case ATMMPC_DATA:
 155                        request_module("mpoa");
 156                        break;
 157                case ATMARPD_CTRL:
 158                        request_module("clip");
 159                        break;
 160                case ATMLEC_CTRL:
 161                        request_module("lec");
 162                        break;
 163        }
 164
 165        error = -ENOIOCTLCMD;
 166
 167        mutex_lock(&ioctl_mutex);
 168        list_for_each(pos, &ioctl_list) {
 169                struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list);
 170                if (try_module_get(ic->owner)) {
 171                        error = ic->ioctl(sock, cmd, arg);
 172                        module_put(ic->owner);
 173                        if (error != -ENOIOCTLCMD)
 174                                break;
 175                }
 176        }
 177        mutex_unlock(&ioctl_mutex);
 178
 179        if (error != -ENOIOCTLCMD)
 180                goto done;
 181
 182        error = atm_dev_ioctl(cmd, argp, compat);
 183
 184done:
 185        return error;
 186}
 187
 188
 189int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 190{
 191        return do_vcc_ioctl(sock, cmd, arg, 0);
 192}
 193
 194#ifdef CONFIG_COMPAT
 195int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 196{
 197        return do_vcc_ioctl(sock, cmd, arg, 1);
 198}
 199#endif
 200