/* * 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 #include #include #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; }