diff options
Diffstat (limited to 'net/ax25/ax25_ctl.c')
-rw-r--r-- | net/ax25/ax25_ctl.c | 133 |
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; +} |