summaryrefslogtreecommitdiffstats
path: root/net/ax25/af_ax25.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-07-20 14:56:40 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-07-20 14:56:40 +0000
commite308faf24f68e262d92d294a01ddca7a17e76762 (patch)
tree22c47cb315811834861f013067878ff664e95abd /net/ax25/af_ax25.c
parent30c6397ce63178fcb3e7963ac247f0a03132aca9 (diff)
Sync with Linux 2.1.46.
Diffstat (limited to 'net/ax25/af_ax25.c')
-rw-r--r--net/ax25/af_ax25.c308
1 files changed, 145 insertions, 163 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 37b679600..8e5992747 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1,5 +1,5 @@
/*
- * AX.25 release 036
+ * AX.25 release 037
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -92,6 +92,7 @@
* AX.25 036 Jonathan(G4KLX) Major restructuring.
* Joerg(DL1BKE) Fixed DAMA Slave.
* Jonathan(G4KLX) Fix widlcard listen parameter setting.
+ * AX.25 037 Jonathan(G4KLX) New timer architecture.
*/
#include <linux/config.h>
@@ -161,8 +162,7 @@ static void ax25_remove_socket(ax25_cb *ax25)
ax25_cb *s;
unsigned long flags;
- save_flags(flags);
- cli();
+ save_flags(flags); cli();
if ((s = ax25_list) == ax25) {
ax25_list = s->next;
@@ -196,16 +196,8 @@ static void ax25_kill_by_device(struct device *dev)
for (s = ax25_list; s != NULL; s = s->next) {
if (s->ax25_dev == ax25_dev) {
- s->state = AX25_STATE_0;
s->ax25_dev = NULL;
- if (s->sk != NULL) {
- s->sk->state = TCP_CLOSE;
- s->sk->err = ENETUNREACH;
- s->sk->shutdown |= SEND_SHUTDOWN;
- if (!s->sk->dead)
- s->sk->state_change(s->sk);
- s->sk->dead = 1;
- }
+ ax25_disconnect(s, ENETUNREACH);
}
}
}
@@ -308,7 +300,7 @@ struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, in
* Find an AX.25 control block given both ends. It will only pick up
* floating AX.25 control blocks or non Raw socket bound control blocks.
*/
-ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, ax25_digi *digi, struct device *dev)
+ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi *digi, struct device *dev)
{
ax25_cb *s;
unsigned long flags;
@@ -319,11 +311,16 @@ ax25_cb *ax25_find_cb(ax25_address *my_addr, ax25_address *dest_addr, ax25_digi
for (s = ax25_list; s != NULL; s = s->next) {
if (s->sk != NULL && s->sk->type != SOCK_SEQPACKET)
continue;
- if (ax25cmp(&s->source_addr, my_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {
- if (digi != NULL) {
- if (s->digipeat == NULL && digi->ndigi != 0)
+ if (s->ax25_dev == NULL)
+ continue;
+ if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {
+ if (digi != NULL && digi->ndigi != 0) {
+ if (s->digipeat == NULL)
continue;
- if (s->digipeat != NULL && ax25digicmp(s->digipeat, digi) != 0)
+ if (ax25digicmp(s->digipeat, digi) != 0)
+ continue;
+ } else {
+ if (s->digipeat != NULL && s->digipeat->ndigi != 0)
continue;
}
restore_flags(flags);
@@ -402,10 +399,13 @@ void ax25_destroy_socket(ax25_cb *ax25) /* Not static as it's used by the timer
struct sk_buff *skb;
unsigned long flags;
- save_flags(flags);
- cli();
+ save_flags(flags); cli();
- del_timer(&ax25->timer);
+ ax25_stop_heartbeat(ax25);
+ ax25_stop_t1timer(ax25);
+ ax25_stop_t2timer(ax25);
+ ax25_stop_t3timer(ax25);
+ ax25_stop_idletimer(ax25);
ax25_remove_socket(ax25);
ax25_clear_queues(ax25); /* Flush the queues */
@@ -414,7 +414,7 @@ void ax25_destroy_socket(ax25_cb *ax25) /* Not static as it's used by the timer
while ((skb = skb_dequeue(&ax25->sk->receive_queue)) != NULL) {
if (skb->sk != ax25->sk) { /* A pending connection */
skb->sk->dead = 1; /* Queue the unaccepted socket for death */
- ax25_set_timer(skb->sk->protinfo.ax25);
+ ax25_start_heartbeat(skb->sk->protinfo.ax25);
skb->sk->protinfo.ax25->state = AX25_STATE_0;
}
@@ -451,13 +451,9 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
struct ax25_ctl_struct ax25_ctl;
ax25_dev *ax25_dev;
ax25_cb *ax25;
- unsigned long flags;
- int err;
-
- if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_ctl))) != 0)
- return err;
- copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl));
+ if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
+ return -EFAULT;
if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
return -ENODEV;
@@ -467,22 +463,12 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
switch (ax25_ctl.cmd) {
case AX25_KILL:
- ax25_clear_queues(ax25);
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
- ax25->state = AX25_STATE_0;
#ifdef CONFIG_AX25_DAMA_SLAVE
if (ax25_dev->dama.slave && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE)
ax25_dama_off(ax25);
#endif
- if (ax25->sk != NULL) {
- ax25->sk->state = TCP_CLOSE;
- ax25->sk->err = ENETRESET;
- ax25->sk->shutdown |= SEND_SHUTDOWN;
- if (!ax25->sk->dead)
- ax25->sk->state_change(ax25->sk);
- ax25->sk->dead = 1;
- }
- ax25_set_timer(ax25);
+ ax25_disconnect(ax25, ENETRESET);
break;
case AX25_WINDOW:
@@ -499,22 +485,14 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
case AX25_T1:
if (ax25_ctl.arg < 1)
return -EINVAL;
- ax25->rtt = (ax25_ctl.arg * AX25_SLOWHZ) / 2;
- ax25->t1 = ax25_ctl.arg * AX25_SLOWHZ;
- save_flags(flags); cli();
- if (ax25->t1timer > ax25->t1)
- ax25->t1timer = ax25->t1;
- restore_flags(flags);
+ ax25->rtt = (ax25_ctl.arg * HZ) / 2;
+ ax25->t1 = ax25_ctl.arg * HZ;
break;
case AX25_T2:
if (ax25_ctl.arg < 1)
return -EINVAL;
- save_flags(flags); cli();
- ax25->t2 = ax25_ctl.arg * AX25_SLOWHZ;
- if (ax25->t2timer > ax25->t2)
- ax25->t2timer = ax25->t2;
- restore_flags(flags);
+ ax25->t2 = ax25_ctl.arg * HZ;
break;
case AX25_N2:
@@ -527,21 +505,13 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
case AX25_T3:
if (ax25_ctl.arg < 0)
return -EINVAL;
- save_flags(flags); cli();
- ax25->t3 = ax25_ctl.arg * AX25_SLOWHZ;
- if (ax25->t3timer != 0)
- ax25->t3timer = ax25->t3;
- restore_flags(flags);
+ ax25->t3 = ax25_ctl.arg * HZ;
break;
case AX25_IDLE:
if (ax25_ctl.arg < 0)
return -EINVAL;
- save_flags(flags); cli();
- ax25->idle = ax25_ctl.arg * AX25_SLOWHZ * 60;
- if (ax25->idletimer != 0)
- ax25->idletimer = ax25->idle;
- restore_flags(flags);
+ ax25->idle = ax25_ctl.arg * 60 * HZ;
break;
case AX25_PACLEN:
@@ -622,6 +592,10 @@ ax25_cb *ax25_create_cb(void)
skb_queue_head_init(&ax25->reseq_queue);
init_timer(&ax25->timer);
+ init_timer(&ax25->t1timer);
+ init_timer(&ax25->t2timer);
+ init_timer(&ax25->t3timer);
+ init_timer(&ax25->idletimer);
ax25_fillin_cb(ax25, NULL);
@@ -664,13 +638,14 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
case AX25_T1:
if (opt < 1)
return -EINVAL;
- sk->protinfo.ax25->rtt = (opt * AX25_SLOWHZ) / 2;
+ sk->protinfo.ax25->rtt = (opt * HZ) / 2;
+ sk->protinfo.ax25->t1 = opt * HZ;
return 0;
case AX25_T2:
if (opt < 1)
return -EINVAL;
- sk->protinfo.ax25->t2 = opt * AX25_SLOWHZ;
+ sk->protinfo.ax25->t2 = opt * HZ;
return 0;
case AX25_N2:
@@ -682,13 +657,13 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
case AX25_T3:
if (opt < 1)
return -EINVAL;
- sk->protinfo.ax25->t3 = opt * AX25_SLOWHZ;
+ sk->protinfo.ax25->t3 = opt * HZ;
return 0;
case AX25_IDLE:
if (opt < 0)
return -EINVAL;
- sk->protinfo.ax25->idle = opt * AX25_SLOWHZ * 60;
+ sk->protinfo.ax25->idle = opt * 60 * HZ;
return 0;
case AX25_BACKOFF:
@@ -738,11 +713,11 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
break;
case AX25_T1:
- val = (sk->protinfo.ax25->t1 * 2) / AX25_SLOWHZ;
+ val = sk->protinfo.ax25->t1 / HZ;
break;
case AX25_T2:
- val = sk->protinfo.ax25->t2 / AX25_SLOWHZ;
+ val = sk->protinfo.ax25->t2 / HZ;
break;
case AX25_N2:
@@ -750,11 +725,11 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
break;
case AX25_T3:
- val = sk->protinfo.ax25->t3 / AX25_SLOWHZ;
+ val = sk->protinfo.ax25->t3 / HZ;
break;
case AX25_IDLE:
- val = sk->protinfo.ax25->idle / (AX25_SLOWHZ * 60);
+ val = sk->protinfo.ax25->idle / (60 * HZ);
break;
case AX25_BACKOFF:
@@ -963,22 +938,14 @@ static int ax25_release(struct socket *sock, struct socket *peer)
if (sk->type == SOCK_SEQPACKET) {
switch (sk->protinfo.ax25->state) {
case AX25_STATE_0:
- sk->state = TCP_CLOSE;
- sk->shutdown |= SEND_SHUTDOWN;
- sk->state_change(sk);
- sk->dead = 1;
+ ax25_disconnect(sk->protinfo.ax25, 0);
ax25_destroy_socket(sk->protinfo.ax25);
break;
case AX25_STATE_1:
case AX25_STATE_2:
- ax25_clear_queues(sk->protinfo.ax25);
ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
- sk->protinfo.ax25->state = AX25_STATE_0;
- sk->state = TCP_CLOSE;
- sk->shutdown |= SEND_SHUTDOWN;
- sk->state_change(sk);
- sk->dead = 1;
+ ax25_disconnect(sk->protinfo.ax25, 0);
ax25_destroy_socket(sk->protinfo.ax25);
break;
@@ -990,31 +957,34 @@ static int ax25_release(struct socket *sock, struct socket *peer)
case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX:
ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
- sk->protinfo.ax25->t3timer = 0;
+ ax25_stop_t2timer(sk->protinfo.ax25);
+ ax25_stop_t3timer(sk->protinfo.ax25);
+ ax25_stop_idletimer(sk->protinfo.ax25);
break;
#ifdef AX25_CONFIG_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE:
- sk->protinfo.ax25->t3timer = 0;
+ ax25_stop_t3timer(sk->protinfo.ax25);
break;
#endif
}
- sk->protinfo.ax25->t1timer = sk->protinfo.ax25->t1 = ax25_calculate_t1(sk->protinfo.ax25);
- sk->protinfo.ax25->state = AX25_STATE_2;
- sk->state = TCP_CLOSE;
- sk->shutdown |= SEND_SHUTDOWN;
+ ax25_calculate_t1(sk->protinfo.ax25);
+ ax25_start_t1timer(sk->protinfo.ax25);
+ sk->protinfo.ax25->state = AX25_STATE_2;
+ sk->state = TCP_CLOSE;
+ sk->shutdown |= SEND_SHUTDOWN;
sk->state_change(sk);
- sk->dead = 1;
- sk->destroy = 1;
+ sk->dead = 1;
+ sk->destroy = 1;
break;
default:
break;
}
} else {
- sk->state = TCP_CLOSE;
- sk->shutdown |= SEND_SHUTDOWN;
+ sk->state = TCP_CLOSE;
+ sk->shutdown |= SEND_SHUTDOWN;
sk->state_change(sk);
- sk->dead = 1;
+ sk->dead = 1;
ax25_destroy_socket(sk->protinfo.ax25);
}
@@ -1092,8 +1062,9 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
{
struct sock *sk = sock->sk;
- struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
- int err;
+ struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;
+ ax25_digi *digi = NULL;
+ int ct = 0, err;
if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED;
@@ -1114,36 +1085,36 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
return -EINVAL;
- if (addr->sax25_family != AF_AX25)
+ if (fsa->fsa_ax25.sax25_family != AF_AX25)
return -EINVAL;
+ if (sk->protinfo.ax25->digipeat != NULL) {
+ kfree(sk->protinfo.ax25->digipeat);
+ sk->protinfo.ax25->digipeat = NULL;
+ }
+
/*
* Handle digi-peaters to be used.
*/
- if (addr_len == sizeof(struct full_sockaddr_ax25) && addr->sax25_ndigis != 0) {
- int ct = 0;
- struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)addr;
-
+ if (addr_len == sizeof(struct full_sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) {
/* Valid number of digipeaters ? */
- if (addr->sax25_ndigis < 1 || addr->sax25_ndigis > AX25_MAX_DIGIS)
+ if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS)
return -EINVAL;
- if (sk->protinfo.ax25->digipeat == NULL) {
- if ((sk->protinfo.ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL)
- return -ENOBUFS;
- }
+ if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL)
+ return -ENOBUFS;
- sk->protinfo.ax25->digipeat->ndigi = addr->sax25_ndigis;
- sk->protinfo.ax25->digipeat->lastrepeat = -1;
+ digi->ndigi = fsa->fsa_ax25.sax25_ndigis;
+ digi->lastrepeat = -1;
- while (ct < addr->sax25_ndigis) {
+ while (ct < fsa->fsa_ax25.sax25_ndigis) {
if ((fsa->fsa_digipeater[ct].ax25_call[6] & AX25_HBIT) && sk->protinfo.ax25->iamdigi) {
- sk->protinfo.ax25->digipeat->repeated[ct] = 1;
- sk->protinfo.ax25->digipeat->lastrepeat = ct;
+ digi->repeated[ct] = 1;
+ digi->lastrepeat = ct;
} else {
- sk->protinfo.ax25->digipeat->repeated[ct] = 0;
+ digi->repeated[ct] = 0;
}
- sk->protinfo.ax25->digipeat->calls[ct] = fsa->fsa_digipeater[ct];
+ digi->calls[ct] = fsa->fsa_digipeater[ct];
ct++;
}
}
@@ -1154,7 +1125,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
* been filled in, error if it hasn't.
*/
if (sk->zapped) {
- if ((err = ax25_rt_autobind(sk->protinfo.ax25, &addr->sax25_call)) < 0)
+ if ((err = ax25_rt_autobind(sk->protinfo.ax25, &fsa->fsa_ax25.sax25_call)) < 0)
return err;
ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev);
ax25_insert_socket(sk->protinfo.ax25);
@@ -1163,10 +1134,13 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
return -EHOSTUNREACH;
}
- if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &addr->sax25_call, NULL, sk->protinfo.ax25->ax25_dev->dev) != NULL)
+ if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi, sk->protinfo.ax25->ax25_dev->dev) != NULL) {
+ if (digi != NULL) kfree(digi);
return -EADDRINUSE; /* Already such a connection */
+ }
- sk->protinfo.ax25->dest_addr = addr->sax25_call;
+ sk->protinfo.ax25->dest_addr = fsa->fsa_ax25.sax25_call;
+ sk->protinfo.ax25->digipeat = digi;
/* First the easy one */
if (sk->type != SOCK_SEQPACKET) {
@@ -1198,7 +1172,8 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
}
sk->protinfo.ax25->state = AX25_STATE_1;
- ax25_set_timer(sk->protinfo.ax25); /* Start going SABM SABM until a UA or a give up and DM */
+
+ ax25_start_heartbeat(sk->protinfo.ax25);
/* Now the loop */
if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
@@ -1532,38 +1507,35 @@ static int ax25_shutdown(struct socket *sk, int how)
static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
- struct ax25_info_struct ax25_info;
- int err;
- long amount = 0;
switch (cmd) {
- case TIOCOUTQ:
- if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
- return err;
+ case TIOCOUTQ: {
+ long amount;
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
amount = 0;
- put_user(amount, (int *)arg);
+ if (put_user(amount, (int *)arg))
+ return -EFAULT;
return 0;
+ }
case TIOCINQ: {
struct sk_buff *skb;
+ long amount = 0L;
/* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL)
amount = skb->len;
- if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
- return err;
- put_user(amount, (int *)arg);
+ if (put_user(amount, (int *)arg))
+ return -EFAULT;
return 0;
}
case SIOCGSTAMP:
if (sk != NULL) {
- if (sk->stamp.tv_sec==0)
+ if (sk->stamp.tv_sec == 0)
return -ENOENT;
- if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
- return err;
- copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval));
+ if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+ return -EFAULT;
return 0;
}
return -EINVAL;
@@ -1572,22 +1544,22 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */
case SIOCAX25GETUID: {
struct sockaddr_ax25 sax25;
- if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(struct sockaddr_ax25))) != 0)
- return err;
- copy_from_user(&sax25, (void *)arg, sizeof(sax25));
+ if (copy_from_user(&sax25, (void *)arg, sizeof(sax25)))
+ return -EFAULT;
return ax25_uid_ioctl(cmd, &sax25);
}
- case SIOCAX25NOUID: /* Set the default policy (default/bar) */
- if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(unsigned long))) != 0)
- return err;
+ case SIOCAX25NOUID: { /* Set the default policy (default/bar) */
+ long amount;
if (!suser())
return -EPERM;
- get_user(amount, (long *)arg);
+ if (get_user(amount, (long *)arg))
+ return -EFAULT;
if (amount > AX25_NOUID_BLOCK)
return -EINVAL;
ax25_uid_policy = amount;
return 0;
+ }
case SIOCADDRT:
case SIOCDELRT:
@@ -1601,33 +1573,33 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return -EPERM;
return ax25_ctl_ioctl(cmd, (void *)arg);
- case SIOCAX25GETINFO:
- if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(ax25_info))) != 0)
- return err;
- ax25_info.t1 = sk->protinfo.ax25->t1;
- ax25_info.t2 = sk->protinfo.ax25->t2;
- ax25_info.t3 = sk->protinfo.ax25->t3;
- ax25_info.idle = sk->protinfo.ax25->idle;
+ case SIOCAX25GETINFO: {
+ struct ax25_info_struct ax25_info;
+ ax25_info.t1 = sk->protinfo.ax25->t1 / HZ;
+ ax25_info.t2 = sk->protinfo.ax25->t2 / HZ;
+ ax25_info.t3 = sk->protinfo.ax25->t3 / HZ;
+ ax25_info.idle = sk->protinfo.ax25->idle / (60 * HZ);
ax25_info.n2 = sk->protinfo.ax25->n2;
- ax25_info.t1timer = sk->protinfo.ax25->t1timer;
- ax25_info.t2timer = sk->protinfo.ax25->t2timer;
- ax25_info.t3timer = sk->protinfo.ax25->t3timer;
- ax25_info.idletimer = sk->protinfo.ax25->idletimer;
+ ax25_info.t1timer = ax25_display_timer(&sk->protinfo.ax25->t1timer) / HZ;
+ ax25_info.t2timer = ax25_display_timer(&sk->protinfo.ax25->t2timer) / HZ;
+ ax25_info.t3timer = ax25_display_timer(&sk->protinfo.ax25->t3timer) / HZ;
+ ax25_info.idletimer = ax25_display_timer(&sk->protinfo.ax25->idletimer) / (60 * HZ);
ax25_info.n2count = sk->protinfo.ax25->n2count;
ax25_info.state = sk->protinfo.ax25->state;
ax25_info.rcv_q = atomic_read(&sk->rmem_alloc);
ax25_info.snd_q = atomic_read(&sk->wmem_alloc);
- copy_to_user((void *)arg, &ax25_info, sizeof(ax25_info));
+ if (copy_to_user((void *)arg, &ax25_info, sizeof(ax25_info)))
+ return -EFAULT;
return 0;
+ }
case SIOCAX25ADDFWD:
case SIOCAX25DELFWD: {
struct ax25_fwd_struct ax25_fwd;
if (!suser())
return -EPERM;
- if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(ax25_fwd))) != 0)
- return err;
- copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd));
+ if (copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd)))
+ return -EFAULT;
return ax25_fwd_ioctl(cmd, &ax25_fwd);
}
@@ -1655,13 +1627,14 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i
{
ax25_cb *ax25;
const char *devname;
+ char callbuf[15];
int len = 0;
off_t pos = 0;
off_t begin = 0;
cli();
- len += sprintf(buffer, "dest_addr src_addr dev st vs vr va t1 t2 t3 idle n2 rtt wnd paclen Snd-Q Rcv-Q\n");
+ len += sprintf(buffer, "dest_addr src_addr dev st vs vr va t1 t2 t3 idle n2 rtt wnd paclen Snd-Q Rcv-Q\n");
for (ax25 = ax25_list; ax25 != NULL; ax25 = ax25->next) {
if (ax25->ax25_dev == NULL)
@@ -1671,20 +1644,28 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i
len += sprintf(buffer + len, "%-9s ",
ax2asc(&ax25->dest_addr));
- len += sprintf(buffer + len, "%-9s %-4s %2d %3d %3d %3d %3d/%03d %2d/%02d %3d/%03d %3d/%03d %2d/%02d %3d %3d %5d",
- ax2asc(&ax25->source_addr), devname,
+
+ sprintf(callbuf, "%s%c", ax2asc(&ax25->source_addr),
+ (ax25->iamdigi) ? '*' : ' ');
+
+ len += sprintf(buffer + len, "%-10s %-4s %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3lu %3d %5d",
+ callbuf,
+ devname,
ax25->state,
- ax25->vs, ax25->vr, ax25->va,
- ax25->t1timer / AX25_SLOWHZ,
- ax25->t1 / AX25_SLOWHZ,
- ax25->t2timer / AX25_SLOWHZ,
- ax25->t2 / AX25_SLOWHZ,
- ax25->t3timer / AX25_SLOWHZ,
- ax25->t3 / AX25_SLOWHZ,
- ax25->idletimer / (AX25_SLOWHZ * 60),
- ax25->idle / (AX25_SLOWHZ * 60),
- ax25->n2count, ax25->n2,
- ax25->rtt / AX25_SLOWHZ,
+ ax25->vs,
+ ax25->vr,
+ ax25->va,
+ ax25_display_timer(&ax25->t1timer) / HZ,
+ ax25->t1 / HZ,
+ ax25_display_timer(&ax25->t2timer) / HZ,
+ ax25->t2 / HZ,
+ ax25_display_timer(&ax25->t3timer) / HZ,
+ ax25->t3 / HZ,
+ ax25_display_timer(&ax25->idletimer) / (60 * HZ),
+ ax25->idle / (60 * HZ),
+ ax25->n2count,
+ ax25->n2,
+ ax25->rtt / HZ,
ax25->window,
ax25->paclen);
@@ -1764,7 +1745,7 @@ static struct notifier_block ax25_dev_notifier = {
EXPORT_SYMBOL(ax25_encapsulate);
EXPORT_SYMBOL(ax25_rebuild_header);
EXPORT_SYMBOL(ax25_findbyuid);
-EXPORT_SYMBOL(ax25_link_up);
+EXPORT_SYMBOL(ax25_find_cb);
EXPORT_SYMBOL(ax25_linkfail_register);
EXPORT_SYMBOL(ax25_linkfail_release);
EXPORT_SYMBOL(ax25_listen_register);
@@ -1777,6 +1758,7 @@ EXPORT_SYMBOL(ax25cmp);
EXPORT_SYMBOL(ax2asc);
EXPORT_SYMBOL(asc2ax);
EXPORT_SYMBOL(null_ax25_address);
+EXPORT_SYMBOL(ax25_display_timer);
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry proc_ax25_route = {
@@ -1815,7 +1797,7 @@ __initfunc(void ax25_proto_init(struct net_proto *pro))
proc_net_register(&proc_ax25_calls);
#endif
- printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.36 for Linux NET3.038 (Linux 2.1)\n");
+ printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET3.038 (Linux 2.1)\n");
}
#ifdef MODULE