linux/net/x25/x25_subr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *      X.25 Packet Layer release 002
   4 *
   5 *      This is ALPHA test software. This code may break your machine,
   6 *      randomly fail to work with new releases, misbehave and/or generally
   7 *      screw up. It might even work.
   8 *
   9 *      This code REQUIRES 2.1.15 or higher
  10 *
  11 *      History
  12 *      X.25 001        Jonathan Naylor   Started coding.
  13 *      X.25 002        Jonathan Naylor   Centralised disconnection processing.
  14 *      mar/20/00       Daniela Squassoni Disabling/enabling of facilities
  15 *                                        negotiation.
  16 *      jun/24/01       Arnaldo C. Melo   use skb_queue_purge, cleanups
  17 *      apr/04/15       Shaun Pereira           Fast select with no
  18 *                                              restriction on response.
  19 */
  20
  21#define pr_fmt(fmt) "X25: " fmt
  22
  23#include <linux/slab.h>
  24#include <linux/kernel.h>
  25#include <linux/string.h>
  26#include <linux/skbuff.h>
  27#include <net/sock.h>
  28#include <net/tcp_states.h>
  29#include <net/x25.h>
  30
  31/*
  32 *      This routine purges all of the queues of frames.
  33 */
  34void x25_clear_queues(struct sock *sk)
  35{
  36        struct x25_sock *x25 = x25_sk(sk);
  37
  38        skb_queue_purge(&sk->sk_write_queue);
  39        skb_queue_purge(&x25->ack_queue);
  40        skb_queue_purge(&x25->interrupt_in_queue);
  41        skb_queue_purge(&x25->interrupt_out_queue);
  42        skb_queue_purge(&x25->fragment_queue);
  43}
  44
  45
  46/*
  47 * This routine purges the input queue of those frames that have been
  48 * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
  49 * SDL diagram.
  50*/
  51void x25_frames_acked(struct sock *sk, unsigned short nr)
  52{
  53        struct sk_buff *skb;
  54        struct x25_sock *x25 = x25_sk(sk);
  55        int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;
  56
  57        /*
  58         * Remove all the ack-ed frames from the ack queue.
  59         */
  60        if (x25->va != nr)
  61                while (skb_peek(&x25->ack_queue) && x25->va != nr) {
  62                        skb = skb_dequeue(&x25->ack_queue);
  63                        kfree_skb(skb);
  64                        x25->va = (x25->va + 1) % modulus;
  65                }
  66}
  67
  68void x25_requeue_frames(struct sock *sk)
  69{
  70        struct sk_buff *skb, *skb_prev = NULL;
  71
  72        /*
  73         * Requeue all the un-ack-ed frames on the output queue to be picked
  74         * up by x25_kick. This arrangement handles the possibility of an empty
  75         * output queue.
  76         */
  77        while ((skb = skb_dequeue(&x25_sk(sk)->ack_queue)) != NULL) {
  78                if (!skb_prev)
  79                        skb_queue_head(&sk->sk_write_queue, skb);
  80                else
  81                        skb_append(skb_prev, skb, &sk->sk_write_queue);
  82                skb_prev = skb;
  83        }
  84}
  85
  86/*
  87 *      Validate that the value of nr is between va and vs. Return true or
  88 *      false for testing.
  89 */
  90int x25_validate_nr(struct sock *sk, unsigned short nr)
  91{
  92        struct x25_sock *x25 = x25_sk(sk);
  93        unsigned short vc = x25->va;
  94        int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;
  95
  96        while (vc != x25->vs) {
  97                if (nr == vc)
  98                        return 1;
  99                vc = (vc + 1) % modulus;
 100        }
 101
 102        return nr == x25->vs ? 1 : 0;
 103}
 104
 105/*
 106 *  This routine is called when the packet layer internally generates a
 107 *  control frame.
 108 */
 109void x25_write_internal(struct sock *sk, int frametype)
 110{
 111        struct x25_sock *x25 = x25_sk(sk);
 112        struct sk_buff *skb;
 113        unsigned char  *dptr;
 114        unsigned char  facilities[X25_MAX_FAC_LEN];
 115        unsigned char  addresses[1 + X25_ADDR_LEN];
 116        unsigned char  lci1, lci2;
 117        /*
 118         *      Default safe frame size.
 119         */
 120        int len = X25_MAX_L2_LEN + X25_EXT_MIN_LEN;
 121
 122        /*
 123         *      Adjust frame size.
 124         */
 125        switch (frametype) {
 126        case X25_CALL_REQUEST:
 127                len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
 128                break;
 129        case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
 130                if (x25->facilities.reverse & 0x80) {
 131                        len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
 132                } else {
 133                        len += 1 + X25_MAX_FAC_LEN;
 134                }
 135                break;
 136        case X25_CLEAR_REQUEST:
 137        case X25_RESET_REQUEST:
 138                len += 2;
 139                break;
 140        case X25_RR:
 141        case X25_RNR:
 142        case X25_REJ:
 143        case X25_CLEAR_CONFIRMATION:
 144        case X25_INTERRUPT_CONFIRMATION:
 145        case X25_RESET_CONFIRMATION:
 146                break;
 147        default:
 148                pr_err("invalid frame type %02X\n", frametype);
 149                return;
 150        }
 151
 152        if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
 153                return;
 154
 155        /*
 156         *      Space for Ethernet and 802.2 LLC headers.
 157         */
 158        skb_reserve(skb, X25_MAX_L2_LEN);
 159
 160        /*
 161         *      Make space for the GFI and LCI, and fill them in.
 162         */
 163        dptr = skb_put(skb, 2);
 164
 165        lci1 = (x25->lci >> 8) & 0x0F;
 166        lci2 = (x25->lci >> 0) & 0xFF;
 167
 168        if (x25->neighbour->extended) {
 169                *dptr++ = lci1 | X25_GFI_EXTSEQ;
 170                *dptr++ = lci2;
 171        } else {
 172                *dptr++ = lci1 | X25_GFI_STDSEQ;
 173                *dptr++ = lci2;
 174        }
 175
 176        /*
 177         *      Now fill in the frame type specific information.
 178         */
 179        switch (frametype) {
 180
 181                case X25_CALL_REQUEST:
 182                        dptr    = skb_put(skb, 1);
 183                        *dptr++ = X25_CALL_REQUEST;
 184                        len     = x25_addr_aton(addresses, &x25->dest_addr,
 185                                                &x25->source_addr);
 186                        skb_put_data(skb, addresses, len);
 187                        len     = x25_create_facilities(facilities,
 188                                        &x25->facilities,
 189                                        &x25->dte_facilities,
 190                                        x25->neighbour->global_facil_mask);
 191                        skb_put_data(skb, facilities, len);
 192                        skb_put_data(skb, x25->calluserdata.cuddata,
 193                                     x25->calluserdata.cudlength);
 194                        x25->calluserdata.cudlength = 0;
 195                        break;
 196
 197                case X25_CALL_ACCEPTED:
 198                        dptr    = skb_put(skb, 2);
 199                        *dptr++ = X25_CALL_ACCEPTED;
 200                        *dptr++ = 0x00;         /* Address lengths */
 201                        len     = x25_create_facilities(facilities,
 202                                                        &x25->facilities,
 203                                                        &x25->dte_facilities,
 204                                                        x25->vc_facil_mask);
 205                        skb_put_data(skb, facilities, len);
 206
 207                        /* fast select with no restriction on response
 208                                allows call user data. Userland must
 209                                ensure it is ours and not theirs */
 210                        if(x25->facilities.reverse & 0x80) {
 211                                skb_put_data(skb,
 212                                             x25->calluserdata.cuddata,
 213                                             x25->calluserdata.cudlength);
 214                        }
 215                        x25->calluserdata.cudlength = 0;
 216                        break;
 217
 218                case X25_CLEAR_REQUEST:
 219                        dptr    = skb_put(skb, 3);
 220                        *dptr++ = frametype;
 221                        *dptr++ = x25->causediag.cause;
 222                        *dptr++ = x25->causediag.diagnostic;
 223                        break;
 224
 225                case X25_RESET_REQUEST:
 226                        dptr    = skb_put(skb, 3);
 227                        *dptr++ = frametype;
 228                        *dptr++ = 0x00;         /* XXX */
 229                        *dptr++ = 0x00;         /* XXX */
 230                        break;
 231
 232                case X25_RR:
 233                case X25_RNR:
 234                case X25_REJ:
 235                        if (x25->neighbour->extended) {
 236                                dptr     = skb_put(skb, 2);
 237                                *dptr++  = frametype;
 238                                *dptr++  = (x25->vr << 1) & 0xFE;
 239                        } else {
 240                                dptr     = skb_put(skb, 1);
 241                                *dptr    = frametype;
 242                                *dptr++ |= (x25->vr << 5) & 0xE0;
 243                        }
 244                        break;
 245
 246                case X25_CLEAR_CONFIRMATION:
 247                case X25_INTERRUPT_CONFIRMATION:
 248                case X25_RESET_CONFIRMATION:
 249                        dptr  = skb_put(skb, 1);
 250                        *dptr = frametype;
 251                        break;
 252        }
 253
 254        x25_transmit_link(skb, x25->neighbour);
 255}
 256
 257/*
 258 *      Unpick the contents of the passed X.25 Packet Layer frame.
 259 */
 260int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
 261               int *d, int *m)
 262{
 263        struct x25_sock *x25 = x25_sk(sk);
 264        unsigned char *frame;
 265
 266        if (!pskb_may_pull(skb, X25_STD_MIN_LEN))
 267                return X25_ILLEGAL;
 268        frame = skb->data;
 269
 270        *ns = *nr = *q = *d = *m = 0;
 271
 272        switch (frame[2]) {
 273        case X25_CALL_REQUEST:
 274        case X25_CALL_ACCEPTED:
 275        case X25_CLEAR_REQUEST:
 276        case X25_CLEAR_CONFIRMATION:
 277        case X25_INTERRUPT:
 278        case X25_INTERRUPT_CONFIRMATION:
 279        case X25_RESET_REQUEST:
 280        case X25_RESET_CONFIRMATION:
 281        case X25_RESTART_REQUEST:
 282        case X25_RESTART_CONFIRMATION:
 283        case X25_REGISTRATION_REQUEST:
 284        case X25_REGISTRATION_CONFIRMATION:
 285        case X25_DIAGNOSTIC:
 286                return frame[2];
 287        }
 288
 289        if (x25->neighbour->extended) {
 290                if (frame[2] == X25_RR  ||
 291                    frame[2] == X25_RNR ||
 292                    frame[2] == X25_REJ) {
 293                        if (!pskb_may_pull(skb, X25_EXT_MIN_LEN))
 294                                return X25_ILLEGAL;
 295                        frame = skb->data;
 296
 297                        *nr = (frame[3] >> 1) & 0x7F;
 298                        return frame[2];
 299                }
 300        } else {
 301                if ((frame[2] & 0x1F) == X25_RR  ||
 302                    (frame[2] & 0x1F) == X25_RNR ||
 303                    (frame[2] & 0x1F) == X25_REJ) {
 304                        *nr = (frame[2] >> 5) & 0x07;
 305                        return frame[2] & 0x1F;
 306                }
 307        }
 308
 309        if (x25->neighbour->extended) {
 310                if ((frame[2] & 0x01) == X25_DATA) {
 311                        if (!pskb_may_pull(skb, X25_EXT_MIN_LEN))
 312                                return X25_ILLEGAL;
 313                        frame = skb->data;
 314
 315                        *q  = (frame[0] & X25_Q_BIT) == X25_Q_BIT;
 316                        *d  = (frame[0] & X25_D_BIT) == X25_D_BIT;
 317                        *m  = (frame[3] & X25_EXT_M_BIT) == X25_EXT_M_BIT;
 318                        *nr = (frame[3] >> 1) & 0x7F;
 319                        *ns = (frame[2] >> 1) & 0x7F;
 320                        return X25_DATA;
 321                }
 322        } else {
 323                if ((frame[2] & 0x01) == X25_DATA) {
 324                        *q  = (frame[0] & X25_Q_BIT) == X25_Q_BIT;
 325                        *d  = (frame[0] & X25_D_BIT) == X25_D_BIT;
 326                        *m  = (frame[2] & X25_STD_M_BIT) == X25_STD_M_BIT;
 327                        *nr = (frame[2] >> 5) & 0x07;
 328                        *ns = (frame[2] >> 1) & 0x07;
 329                        return X25_DATA;
 330                }
 331        }
 332
 333        pr_debug("invalid PLP frame %3ph\n", frame);
 334
 335        return X25_ILLEGAL;
 336}
 337
 338void x25_disconnect(struct sock *sk, int reason, unsigned char cause,
 339                    unsigned char diagnostic)
 340{
 341        struct x25_sock *x25 = x25_sk(sk);
 342
 343        x25_clear_queues(sk);
 344        x25_stop_timer(sk);
 345
 346        x25->lci   = 0;
 347        x25->state = X25_STATE_0;
 348
 349        x25->causediag.cause      = cause;
 350        x25->causediag.diagnostic = diagnostic;
 351
 352        sk->sk_state     = TCP_CLOSE;
 353        sk->sk_err       = reason;
 354        sk->sk_shutdown |= SEND_SHUTDOWN;
 355
 356        if (!sock_flag(sk, SOCK_DEAD)) {
 357                sk->sk_state_change(sk);
 358                sock_set_flag(sk, SOCK_DEAD);
 359        }
 360        if (x25->neighbour) {
 361                read_lock_bh(&x25_list_lock);
 362                x25_neigh_put(x25->neighbour);
 363                x25->neighbour = NULL;
 364                read_unlock_bh(&x25_list_lock);
 365        }
 366}
 367
 368/*
 369 * Clear an own-rx-busy condition and tell the peer about this, provided
 370 * that there is a significant amount of free receive buffer space available.
 371 */
 372void x25_check_rbuf(struct sock *sk)
 373{
 374        struct x25_sock *x25 = x25_sk(sk);
 375
 376        if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf >> 1) &&
 377            (x25->condition & X25_COND_OWN_RX_BUSY)) {
 378                x25->condition &= ~X25_COND_OWN_RX_BUSY;
 379                x25->condition &= ~X25_COND_ACK_PENDING;
 380                x25->vl         = x25->vr;
 381                x25_write_internal(sk, X25_RR);
 382                x25_stop_timer(sk);
 383        }
 384}
 385