root/net/ax25/ax25_ds_subr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ax25_ds_nr_error_recovery
  2. ax25_ds_enquiry_response
  3. ax25_ds_establish_data_link
  4. ax25_kiss_cmd
  5. ax25_check_dama_slave
  6. ax25_dev_dama_on
  7. ax25_dev_dama_off
  8. ax25_dama_on
  9. ax25_dama_off

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *
   4  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   5  * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
   6  */
   7 #include <linux/errno.h>
   8 #include <linux/types.h>
   9 #include <linux/socket.h>
  10 #include <linux/in.h>
  11 #include <linux/kernel.h>
  12 #include <linux/timer.h>
  13 #include <linux/string.h>
  14 #include <linux/sockios.h>
  15 #include <linux/spinlock.h>
  16 #include <linux/net.h>
  17 #include <linux/gfp.h>
  18 #include <net/ax25.h>
  19 #include <linux/inet.h>
  20 #include <linux/netdevice.h>
  21 #include <linux/skbuff.h>
  22 #include <net/sock.h>
  23 #include <linux/uaccess.h>
  24 #include <linux/fcntl.h>
  25 #include <linux/mm.h>
  26 #include <linux/interrupt.h>
  27 
  28 void ax25_ds_nr_error_recovery(ax25_cb *ax25)
  29 {
  30         ax25_ds_establish_data_link(ax25);
  31 }
  32 
  33 /*
  34  *      dl1bke 960114: transmit I frames on DAMA poll
  35  */
  36 void ax25_ds_enquiry_response(ax25_cb *ax25)
  37 {
  38         ax25_cb *ax25o;
  39 
  40         /* Please note that neither DK4EG's nor DG2FEF's
  41          * DAMA spec mention the following behaviour as seen
  42          * with TheFirmware:
  43          *
  44          *      DB0ACH->DL1BKE <RR C P R0> [DAMA]
  45          *      DL1BKE->DB0ACH <I NR=0 NS=0>
  46          *      DL1BKE-7->DB0PRA-6 DB0ACH <I C S3 R5>
  47          *      DL1BKE->DB0ACH <RR R F R0>
  48          *
  49          * The Flexnet DAMA Master implementation apparently
  50          * insists on the "proper" AX.25 behaviour:
  51          *
  52          *      DB0ACH->DL1BKE <RR C P R0> [DAMA]
  53          *      DL1BKE->DB0ACH <RR R F R0>
  54          *      DL1BKE->DB0ACH <I NR=0 NS=0>
  55          *      DL1BKE-7->DB0PRA-6 DB0ACH <I C S3 R5>
  56          *
  57          * Flexnet refuses to send us *any* I frame if we send
  58          * a REJ in case AX25_COND_REJECT is set. It is superfluous in
  59          * this mode anyway (a RR or RNR invokes the retransmission).
  60          * Is this a Flexnet bug?
  61          */
  62 
  63         ax25_std_enquiry_response(ax25);
  64 
  65         if (!(ax25->condition & AX25_COND_PEER_RX_BUSY)) {
  66                 ax25_requeue_frames(ax25);
  67                 ax25_kick(ax25);
  68         }
  69 
  70         if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2 || skb_peek(&ax25->ack_queue) != NULL)
  71                 ax25_ds_t1_timeout(ax25);
  72         else
  73                 ax25->n2count = 0;
  74 
  75         ax25_start_t3timer(ax25);
  76         ax25_ds_set_timer(ax25->ax25_dev);
  77 
  78         spin_lock(&ax25_list_lock);
  79         ax25_for_each(ax25o, &ax25_list) {
  80                 if (ax25o == ax25)
  81                         continue;
  82 
  83                 if (ax25o->ax25_dev != ax25->ax25_dev)
  84                         continue;
  85 
  86                 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2) {
  87                         ax25_ds_t1_timeout(ax25o);
  88                         continue;
  89                 }
  90 
  91                 if (!(ax25o->condition & AX25_COND_PEER_RX_BUSY) && ax25o->state == AX25_STATE_3) {
  92                         ax25_requeue_frames(ax25o);
  93                         ax25_kick(ax25o);
  94                 }
  95 
  96                 if (ax25o->state == AX25_STATE_1 || ax25o->state == AX25_STATE_2 || skb_peek(&ax25o->ack_queue) != NULL)
  97                         ax25_ds_t1_timeout(ax25o);
  98 
  99                 /* do not start T3 for listening sockets (tnx DD8NE) */
 100 
 101                 if (ax25o->state != AX25_STATE_0)
 102                         ax25_start_t3timer(ax25o);
 103         }
 104         spin_unlock(&ax25_list_lock);
 105 }
 106 
 107 void ax25_ds_establish_data_link(ax25_cb *ax25)
 108 {
 109         ax25->condition &= AX25_COND_DAMA_MODE;
 110         ax25->n2count    = 0;
 111         ax25_calculate_t1(ax25);
 112         ax25_start_t1timer(ax25);
 113         ax25_stop_t2timer(ax25);
 114         ax25_start_t3timer(ax25);
 115 }
 116 
 117 /*
 118  *      :::FIXME:::
 119  *      This is a kludge. Not all drivers recognize kiss commands.
 120  *      We need a driver level  request to switch duplex mode, that does
 121  *      either SCC changing, PI config or KISS as required. Currently
 122  *      this request isn't reliable.
 123  */
 124 static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char param)
 125 {
 126         struct sk_buff *skb;
 127         unsigned char *p;
 128 
 129         if (ax25_dev->dev == NULL)
 130                 return;
 131 
 132         if ((skb = alloc_skb(2, GFP_ATOMIC)) == NULL)
 133                 return;
 134 
 135         skb_reset_network_header(skb);
 136         p = skb_put(skb, 2);
 137 
 138         *p++ = cmd;
 139         *p++ = param;
 140 
 141         skb->protocol = ax25_type_trans(skb, ax25_dev->dev);
 142 
 143         dev_queue_xmit(skb);
 144 }
 145 
 146 /*
 147  *      A nasty problem arises if we count the number of DAMA connections
 148  *      wrong, especially when connections on the device already existed
 149  *      and our network node (or the sysop) decides to turn on DAMA Master
 150  *      mode. We thus flag the 'real' slave connections with
 151  *      ax25->dama_slave=1 and look on every disconnect if still slave
 152  *      connections exist.
 153  */
 154 static int ax25_check_dama_slave(ax25_dev *ax25_dev)
 155 {
 156         ax25_cb *ax25;
 157         int res = 0;
 158 
 159         spin_lock(&ax25_list_lock);
 160         ax25_for_each(ax25, &ax25_list)
 161                 if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1) {
 162                         res = 1;
 163                         break;
 164                 }
 165         spin_unlock(&ax25_list_lock);
 166 
 167         return res;
 168 }
 169 
 170 static void ax25_dev_dama_on(ax25_dev *ax25_dev)
 171 {
 172         if (ax25_dev == NULL)
 173                 return;
 174 
 175         if (ax25_dev->dama.slave == 0)
 176                 ax25_kiss_cmd(ax25_dev, 5, 1);
 177 
 178         ax25_dev->dama.slave = 1;
 179         ax25_ds_set_timer(ax25_dev);
 180 }
 181 
 182 void ax25_dev_dama_off(ax25_dev *ax25_dev)
 183 {
 184         if (ax25_dev == NULL)
 185                 return;
 186 
 187         if (ax25_dev->dama.slave && !ax25_check_dama_slave(ax25_dev)) {
 188                 ax25_kiss_cmd(ax25_dev, 5, 0);
 189                 ax25_dev->dama.slave = 0;
 190                 ax25_ds_del_timer(ax25_dev);
 191         }
 192 }
 193 
 194 void ax25_dama_on(ax25_cb *ax25)
 195 {
 196         ax25_dev_dama_on(ax25->ax25_dev);
 197         ax25->condition |= AX25_COND_DAMA_MODE;
 198 }
 199 
 200 void ax25_dama_off(ax25_cb *ax25)
 201 {
 202         ax25->condition &= ~AX25_COND_DAMA_MODE;
 203         ax25_dev_dama_off(ax25->ax25_dev);
 204 }

/* [<][>][^][v][top][bottom][index][help] */