Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  LAPB release 002
0004  *
0005  *  This code REQUIRES 2.1.15 or higher/ NET3.038
0006  *
0007  *  History
0008  *  LAPB 001    Jonathan Naylor Started Coding
0009  */
0010 
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012 
0013 #include <linux/errno.h>
0014 #include <linux/types.h>
0015 #include <linux/socket.h>
0016 #include <linux/in.h>
0017 #include <linux/kernel.h>
0018 #include <linux/timer.h>
0019 #include <linux/string.h>
0020 #include <linux/sockios.h>
0021 #include <linux/net.h>
0022 #include <linux/inet.h>
0023 #include <linux/skbuff.h>
0024 #include <linux/slab.h>
0025 #include <net/sock.h>
0026 #include <linux/uaccess.h>
0027 #include <linux/fcntl.h>
0028 #include <linux/mm.h>
0029 #include <linux/interrupt.h>
0030 #include <net/lapb.h>
0031 
0032 /*
0033  *  This routine purges all the queues of frames.
0034  */
0035 void lapb_clear_queues(struct lapb_cb *lapb)
0036 {
0037     skb_queue_purge(&lapb->write_queue);
0038     skb_queue_purge(&lapb->ack_queue);
0039 }
0040 
0041 /*
0042  * This routine purges the input queue of those frames that have been
0043  * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
0044  * SDL diagram.
0045  */
0046 void lapb_frames_acked(struct lapb_cb *lapb, unsigned short nr)
0047 {
0048     struct sk_buff *skb;
0049     int modulus;
0050 
0051     modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS;
0052 
0053     /*
0054      * Remove all the ack-ed frames from the ack queue.
0055      */
0056     if (lapb->va != nr)
0057         while (skb_peek(&lapb->ack_queue) && lapb->va != nr) {
0058             skb = skb_dequeue(&lapb->ack_queue);
0059             kfree_skb(skb);
0060             lapb->va = (lapb->va + 1) % modulus;
0061         }
0062 }
0063 
0064 void lapb_requeue_frames(struct lapb_cb *lapb)
0065 {
0066     struct sk_buff *skb, *skb_prev = NULL;
0067 
0068     /*
0069      * Requeue all the un-ack-ed frames on the output queue to be picked
0070      * up by lapb_kick called from the timer. This arrangement handles the
0071      * possibility of an empty output queue.
0072      */
0073     while ((skb = skb_dequeue(&lapb->ack_queue)) != NULL) {
0074         if (!skb_prev)
0075             skb_queue_head(&lapb->write_queue, skb);
0076         else
0077             skb_append(skb_prev, skb, &lapb->write_queue);
0078         skb_prev = skb;
0079     }
0080 }
0081 
0082 /*
0083  *  Validate that the value of nr is between va and vs. Return true or
0084  *  false for testing.
0085  */
0086 int lapb_validate_nr(struct lapb_cb *lapb, unsigned short nr)
0087 {
0088     unsigned short vc = lapb->va;
0089     int modulus;
0090 
0091     modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS;
0092 
0093     while (vc != lapb->vs) {
0094         if (nr == vc)
0095             return 1;
0096         vc = (vc + 1) % modulus;
0097     }
0098 
0099     return nr == lapb->vs;
0100 }
0101 
0102 /*
0103  *  This routine is the centralised routine for parsing the control
0104  *  information for the different frame formats.
0105  */
0106 int lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb,
0107         struct lapb_frame *frame)
0108 {
0109     frame->type = LAPB_ILLEGAL;
0110 
0111     lapb_dbg(2, "(%p) S%d RX %3ph\n", lapb->dev, lapb->state, skb->data);
0112 
0113     /* We always need to look at 2 bytes, sometimes we need
0114      * to look at 3 and those cases are handled below.
0115      */
0116     if (!pskb_may_pull(skb, 2))
0117         return -1;
0118 
0119     if (lapb->mode & LAPB_MLP) {
0120         if (lapb->mode & LAPB_DCE) {
0121             if (skb->data[0] == LAPB_ADDR_D)
0122                 frame->cr = LAPB_COMMAND;
0123             if (skb->data[0] == LAPB_ADDR_C)
0124                 frame->cr = LAPB_RESPONSE;
0125         } else {
0126             if (skb->data[0] == LAPB_ADDR_C)
0127                 frame->cr = LAPB_COMMAND;
0128             if (skb->data[0] == LAPB_ADDR_D)
0129                 frame->cr = LAPB_RESPONSE;
0130         }
0131     } else {
0132         if (lapb->mode & LAPB_DCE) {
0133             if (skb->data[0] == LAPB_ADDR_B)
0134                 frame->cr = LAPB_COMMAND;
0135             if (skb->data[0] == LAPB_ADDR_A)
0136                 frame->cr = LAPB_RESPONSE;
0137         } else {
0138             if (skb->data[0] == LAPB_ADDR_A)
0139                 frame->cr = LAPB_COMMAND;
0140             if (skb->data[0] == LAPB_ADDR_B)
0141                 frame->cr = LAPB_RESPONSE;
0142         }
0143     }
0144 
0145     skb_pull(skb, 1);
0146 
0147     if (lapb->mode & LAPB_EXTENDED) {
0148         if (!(skb->data[0] & LAPB_S)) {
0149             if (!pskb_may_pull(skb, 2))
0150                 return -1;
0151             /*
0152              * I frame - carries NR/NS/PF
0153              */
0154             frame->type       = LAPB_I;
0155             frame->ns         = (skb->data[0] >> 1) & 0x7F;
0156             frame->nr         = (skb->data[1] >> 1) & 0x7F;
0157             frame->pf         = skb->data[1] & LAPB_EPF;
0158             frame->control[0] = skb->data[0];
0159             frame->control[1] = skb->data[1];
0160             skb_pull(skb, 2);
0161         } else if ((skb->data[0] & LAPB_U) == 1) {
0162             if (!pskb_may_pull(skb, 2))
0163                 return -1;
0164             /*
0165              * S frame - take out PF/NR
0166              */
0167             frame->type       = skb->data[0] & 0x0F;
0168             frame->nr         = (skb->data[1] >> 1) & 0x7F;
0169             frame->pf         = skb->data[1] & LAPB_EPF;
0170             frame->control[0] = skb->data[0];
0171             frame->control[1] = skb->data[1];
0172             skb_pull(skb, 2);
0173         } else if ((skb->data[0] & LAPB_U) == 3) {
0174             /*
0175              * U frame - take out PF
0176              */
0177             frame->type       = skb->data[0] & ~LAPB_SPF;
0178             frame->pf         = skb->data[0] & LAPB_SPF;
0179             frame->control[0] = skb->data[0];
0180             frame->control[1] = 0x00;
0181             skb_pull(skb, 1);
0182         }
0183     } else {
0184         if (!(skb->data[0] & LAPB_S)) {
0185             /*
0186              * I frame - carries NR/NS/PF
0187              */
0188             frame->type = LAPB_I;
0189             frame->ns   = (skb->data[0] >> 1) & 0x07;
0190             frame->nr   = (skb->data[0] >> 5) & 0x07;
0191             frame->pf   = skb->data[0] & LAPB_SPF;
0192         } else if ((skb->data[0] & LAPB_U) == 1) {
0193             /*
0194              * S frame - take out PF/NR
0195              */
0196             frame->type = skb->data[0] & 0x0F;
0197             frame->nr   = (skb->data[0] >> 5) & 0x07;
0198             frame->pf   = skb->data[0] & LAPB_SPF;
0199         } else if ((skb->data[0] & LAPB_U) == 3) {
0200             /*
0201              * U frame - take out PF
0202              */
0203             frame->type = skb->data[0] & ~LAPB_SPF;
0204             frame->pf   = skb->data[0] & LAPB_SPF;
0205         }
0206 
0207         frame->control[0] = skb->data[0];
0208 
0209         skb_pull(skb, 1);
0210     }
0211 
0212     return 0;
0213 }
0214 
0215 /*
0216  *  This routine is called when the HDLC layer internally  generates a
0217  *  command or  response  for  the remote machine ( eg. RR, UA etc. ).
0218  *  Only supervisory or unnumbered frames are processed, FRMRs are handled
0219  *  by lapb_transmit_frmr below.
0220  */
0221 void lapb_send_control(struct lapb_cb *lapb, int frametype,
0222                int poll_bit, int type)
0223 {
0224     struct sk_buff *skb;
0225     unsigned char  *dptr;
0226 
0227     if ((skb = alloc_skb(LAPB_HEADER_LEN + 3, GFP_ATOMIC)) == NULL)
0228         return;
0229 
0230     skb_reserve(skb, LAPB_HEADER_LEN + 1);
0231 
0232     if (lapb->mode & LAPB_EXTENDED) {
0233         if ((frametype & LAPB_U) == LAPB_U) {
0234             dptr   = skb_put(skb, 1);
0235             *dptr  = frametype;
0236             *dptr |= poll_bit ? LAPB_SPF : 0;
0237         } else {
0238             dptr     = skb_put(skb, 2);
0239             dptr[0]  = frametype;
0240             dptr[1]  = (lapb->vr << 1);
0241             dptr[1] |= poll_bit ? LAPB_EPF : 0;
0242         }
0243     } else {
0244         dptr   = skb_put(skb, 1);
0245         *dptr  = frametype;
0246         *dptr |= poll_bit ? LAPB_SPF : 0;
0247         if ((frametype & LAPB_U) == LAPB_S) /* S frames carry NR */
0248             *dptr |= (lapb->vr << 5);
0249     }
0250 
0251     lapb_transmit_buffer(lapb, skb, type);
0252 }
0253 
0254 /*
0255  *  This routine generates FRMRs based on information previously stored in
0256  *  the LAPB control block.
0257  */
0258 void lapb_transmit_frmr(struct lapb_cb *lapb)
0259 {
0260     struct sk_buff *skb;
0261     unsigned char  *dptr;
0262 
0263     if ((skb = alloc_skb(LAPB_HEADER_LEN + 7, GFP_ATOMIC)) == NULL)
0264         return;
0265 
0266     skb_reserve(skb, LAPB_HEADER_LEN + 1);
0267 
0268     if (lapb->mode & LAPB_EXTENDED) {
0269         dptr    = skb_put(skb, 6);
0270         *dptr++ = LAPB_FRMR;
0271         *dptr++ = lapb->frmr_data.control[0];
0272         *dptr++ = lapb->frmr_data.control[1];
0273         *dptr++ = (lapb->vs << 1) & 0xFE;
0274         *dptr   = (lapb->vr << 1) & 0xFE;
0275         if (lapb->frmr_data.cr == LAPB_RESPONSE)
0276             *dptr |= 0x01;
0277         dptr++;
0278         *dptr++ = lapb->frmr_type;
0279 
0280         lapb_dbg(1, "(%p) S%d TX FRMR %5ph\n",
0281              lapb->dev, lapb->state,
0282              &skb->data[1]);
0283     } else {
0284         dptr    = skb_put(skb, 4);
0285         *dptr++ = LAPB_FRMR;
0286         *dptr++ = lapb->frmr_data.control[0];
0287         *dptr   = (lapb->vs << 1) & 0x0E;
0288         *dptr  |= (lapb->vr << 5) & 0xE0;
0289         if (lapb->frmr_data.cr == LAPB_RESPONSE)
0290             *dptr |= 0x10;
0291         dptr++;
0292         *dptr++ = lapb->frmr_type;
0293 
0294         lapb_dbg(1, "(%p) S%d TX FRMR %3ph\n",
0295              lapb->dev, lapb->state, &skb->data[1]);
0296     }
0297 
0298     lapb_transmit_buffer(lapb, skb, LAPB_RESPONSE);
0299 }