summaryrefslogtreecommitdiffstats
path: root/net/ax25/ax25_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ax25/ax25_ctl.c')
-rw-r--r--net/ax25/ax25_ctl.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/net/ax25/ax25_ctl.c b/net/ax25/ax25_ctl.c
new file mode 100644
index 000000000..da4cd49c8
--- /dev/null
+++ b/net/ax25/ax25_ctl.c
@@ -0,0 +1,133 @@
+/*
+ * ax25_ctl.c: Implements ioctl()s on persisting VC sockets (NEW-AX.25)
+ *
+ * Authors: Jens David (DG1KJD), Matthias Welwarsky (DG2FEF), Joerg (DL1BKE)
+ *
+ * Comment:
+ *
+ * Changelog:
+ *
+ * License: This module is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/uaccess.h>
+#include <linux/ax25.h>
+#include <net/ax25.h>
+
+#include "af_ax25.h"
+#include "ax25_in.h"
+#include "ax25_subr.h"
+#include "ax25_timer.h"
+
+/*
+ * dl1bke 960311: set parameters for existing AX.25 connections,
+ * includes a KILL command to abort any connection.
+ * VERY useful for debugging ;-)
+ */
+int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
+{
+ struct ax25_ctl_struct ax25_ctl;
+ struct net_device *dev;
+ ax25_cb *ax25;
+ ax25_addr_t addr;
+ int err;
+
+ if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_ctl))) != 0)
+ return err;
+
+ if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
+ return -EFAULT;;
+
+ if ((dev = ax25rtr_get_dev(&ax25_ctl.port_addr)) == NULL)
+ return -ENODEV;
+
+ addr.src = ax25_ctl.source_addr;
+ addr.dest = ax25_ctl.dest_addr;
+ addr.dcount = 0;
+
+ if ((ax25 = ax25_find_cb(&addr, dev)) == NULL)
+ return -ENOTCONN;
+
+ switch (ax25_ctl.cmd) {
+ case AX25_KILL:
+ ax25_tx_command(ax25, AX25_DISC, AX25_POLLON);
+ ax25_set_cond(ax25, AX25_COND_STATE_CHANGE);
+ ax25_disconnect(ax25, ENETRESET);
+ if (ax25->sk)
+ ax25_close_socket(ax25->sk, ENETRESET);
+ break;
+
+ case AX25_WINDOW:
+ if (ax25->seqmask == AX25_SEQMASK) {
+ if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
+ return -EINVAL;
+ } else {
+ if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
+ return -EINVAL;
+ }
+ ax25->window = ax25_ctl.arg;
+ break;
+
+ case AX25_T1:
+ if (ax25_ctl.arg < 1)
+ return -EINVAL;
+ ax25->rtt = (ax25_ctl.arg * AX25_TICS) / 4;
+ ax25->t1 = ax25_ctl.arg;
+ write_lock(&ax25->timer_lock);
+ if (ax25->wrt_timer > ax25->t1)
+ ax25->wrt_timer = ax25->t1;
+ write_unlock(&ax25->timer_lock);
+ break;
+
+ case AX25_T2:
+ if (ax25_ctl.arg < 0)
+ return -EINVAL;
+ ax25->t2 = ax25_ctl.arg;
+ write_lock(&ax25->timer_lock);
+ if (ax25->ack_timer > ax25->t2)
+ ax25->ack_timer = ax25->t2;
+ write_unlock(&ax25->timer_lock);
+ break;
+
+ case AX25_N2:
+ if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
+ return -EINVAL;
+ ax25->n2count = 0;
+ ax25->n2 = ax25_ctl.arg;
+ break;
+
+ case AX25_T3:
+ if (ax25_ctl.arg < 0)
+ return -EINVAL;
+ ax25->t3 = ax25_ctl.arg * AX25_SLOWHZ;
+ write_lock(&ax25->timer_lock);
+ if (ax25->wrt_timer != 0)
+ ax25->wrt_timer = ax25->t3;
+ write_unlock(&ax25->timer_lock);
+ break;
+
+ case AX25_IDLE:
+ if (ax25_ctl.arg < 0)
+ return -EINVAL;
+ ax25->idle = ax25_ctl.arg * AX25_SLOWHZ;
+ write_lock(&ax25->timer_lock);
+ if (ax25->idletimer != 0)
+ ax25->idletimer = ax25->idle;
+ write_unlock(&ax25->timer_lock);
+ break;
+
+ case AX25_PACLEN:
+ if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
+ return -EINVAL;
+ ax25->paclen = ax25_ctl.arg;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}