summary refs log tree commit diff
path: root/net/atm/ioctl.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/atm/ioctl.c
downloadlinux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.gz
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
Diffstat (limited to 'net/atm/ioctl.c')
-rw-r--r--net/atm/ioctl.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
new file mode 100644
index 000000000000..4dbb5af34a5e
--- /dev/null
+++ b/net/atm/ioctl.c
@@ -0,0 +1,139 @@
+/* ATM ioctl handling */
+
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
+/* 2003 John Levon  <levon@movementarian.org> */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/net.h>		/* struct socket, struct proto_ops */
+#include <linux/atm.h>		/* ATM stuff */
+#include <linux/atmdev.h>
+#include <linux/atmclip.h>	/* CLIP_*ENCAP */
+#include <linux/atmarp.h>	/* manifest constants */
+#include <linux/sonet.h>	/* for ioctls */
+#include <linux/atmsvc.h>
+#include <linux/atmmpc.h>
+#include <net/atmclip.h>
+#include <linux/atmlec.h>
+#include <asm/ioctls.h>
+
+#include "resources.h"
+#include "signaling.h"		/* for WAITING and sigd_attach */
+
+
+static DECLARE_MUTEX(ioctl_mutex);
+static LIST_HEAD(ioctl_list);
+
+
+void register_atm_ioctl(struct atm_ioctl *ioctl)
+{
+	down(&ioctl_mutex);
+	list_add_tail(&ioctl->list, &ioctl_list);
+	up(&ioctl_mutex);
+}
+
+void deregister_atm_ioctl(struct atm_ioctl *ioctl)
+{
+	down(&ioctl_mutex);
+	list_del(&ioctl->list);
+	up(&ioctl_mutex);
+}
+
+EXPORT_SYMBOL(register_atm_ioctl);
+EXPORT_SYMBOL(deregister_atm_ioctl);
+
+int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	struct sock *sk = sock->sk;
+	struct atm_vcc *vcc;
+	int error;
+	struct list_head * pos;
+	void __user *argp = (void __user *)arg;
+
+	vcc = ATM_SD(sock);
+	switch (cmd) {
+		case SIOCOUTQ:
+			if (sock->state != SS_CONNECTED ||
+			    !test_bit(ATM_VF_READY, &vcc->flags)) {
+				error =  -EINVAL;
+				goto done;
+			}
+			error = put_user(sk->sk_sndbuf -
+					 atomic_read(&sk->sk_wmem_alloc),
+					 (int __user *) argp) ? -EFAULT : 0;
+			goto done;
+		case SIOCINQ:
+			{
+				struct sk_buff *skb;
+
+				if (sock->state != SS_CONNECTED) {
+					error = -EINVAL;
+					goto done;
+				}
+				skb = skb_peek(&sk->sk_receive_queue);
+				error = put_user(skb ? skb->len : 0,
+					 	 (int __user *)argp) ? -EFAULT : 0;
+				goto done;
+			}
+		case SIOCGSTAMP: /* borrowed from IP */
+			error = sock_get_timestamp(sk, argp);
+			goto done;
+		case ATM_SETSC:
+			printk(KERN_WARNING "ATM_SETSC is obsolete\n");
+			error = 0;
+			goto done;
+		case ATMSIGD_CTRL:
+			if (!capable(CAP_NET_ADMIN)) {
+				error = -EPERM;
+				goto done;
+			}
+			/*
+			 * The user/kernel protocol for exchanging signalling
+			 * info uses kernel pointers as opaque references,
+			 * so the holder of the file descriptor can scribble
+			 * on the kernel... so we should make sure that we
+			 * have the same privledges that /proc/kcore needs
+			 */
+			if (!capable(CAP_SYS_RAWIO)) {
+				error = -EPERM;
+				goto done;
+			}
+			error = sigd_attach(vcc);
+			if (!error)
+				sock->state = SS_CONNECTED;
+			goto done;
+		default:
+			break;
+	}
+
+	if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA)
+		request_module("mpoa");
+	if (cmd == ATMARPD_CTRL)
+		request_module("clip");
+	if (cmd == ATMLEC_CTRL)
+		request_module("lec");
+
+	error = -ENOIOCTLCMD;
+
+	down(&ioctl_mutex);
+	list_for_each(pos, &ioctl_list) {
+		struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list);
+		if (try_module_get(ic->owner)) {
+			error = ic->ioctl(sock, cmd, arg);
+			module_put(ic->owner);
+			if (error != -ENOIOCTLCMD)
+				break;
+		}
+	}
+	up(&ioctl_mutex);
+
+	if (error != -ENOIOCTLCMD)
+		goto done;
+
+	error = atm_dev_ioctl(cmd, argp);
+
+done:
+	return error;
+}