1 /* 2 * LAPB release 002 3 * 4 * This code REQUIRES 2.1.15 or higher/ NET3.038 5 * 6 * This module: 7 * This module is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 10 * 2 of the License, or (at your option) any later version. 11 * 12 * History 13 * LAPB 001 Jonathan Naylor Started Coding 14 */ 15 16 #include <linux/errno.h> 17 #include <linux/types.h> 18 #include <linux/socket.h> 19 #include <linux/in.h> 20 #include <linux/kernel.h> 21 #include <linux/timer.h> 22 #include <linux/string.h> 23 #include <linux/sockios.h> 24 #include <linux/net.h> 25 #include <linux/inet.h> 26 #include <linux/skbuff.h> 27 #include <linux/slab.h> 28 #include <net/sock.h> 29 #include <asm/uaccess.h> 30 #include <asm/system.h> 31 #include <linux/fcntl.h> 32 #include <linux/mm.h> 33 #include <linux/interrupt.h> 34 #include <net/lapb.h> 35 36 /* 37 * This routine purges all the queues of frames. 38 */ 39 void lapb_clear_queues(struct lapb_cb *lapb) 40 { 41 skb_queue_purge(&lapb->write_queue); 42 skb_queue_purge(&lapb->ack_queue); 43 } 44 45 /* 46 * This routine purges the input queue of those frames that have been 47 * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the 48 * SDL diagram. 49 */ 50 void lapb_frames_acked(struct lapb_cb *lapb, unsigned short nr) 51 { 52 struct sk_buff *skb; 53 int modulus; 54 55 modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; 56 57 /* 58 * Remove all the ack-ed frames from the ack queue. 59 */ 60 if (lapb->va != nr) 61 while (skb_peek(&lapb->ack_queue) && lapb->va != nr) { 62 skb = skb_dequeue(&lapb->ack_queue); 63 kfree_skb(skb); 64 lapb->va = (lapb->va + 1) % modulus; 65 } 66 } 67 68 void lapb_requeue_frames(struct lapb_cb *lapb) 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 lapb_kick called from the timer. This arrangement handles the 75 * possibility of an empty output queue. 76 */ 77 while ((skb = skb_dequeue(&lapb->ack_queue)) != NULL) { 78 if (!skb_prev) 79 skb_queue_head(&lapb->write_queue, skb); 80 else 81 skb_append(skb_prev, skb, &lapb->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 */ 90 int lapb_validate_nr(struct lapb_cb *lapb, unsigned short nr) 91 { 92 unsigned short vc = lapb->va; 93 int modulus; 94 95 modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; 96 97 while (vc != lapb->vs) { 98 if (nr == vc) 99 return 1; 100 vc = (vc + 1) % modulus; 101 } 102 103 return nr == lapb->vs; 104 } 105 106 /* 107 * This routine is the centralised routine for parsing the control 108 * information for the different frame formats. 109 */ 110 int lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb, 111 struct lapb_frame *frame) 112 { 113 frame->type = LAPB_ILLEGAL; 114 115 #if LAPB_DEBUG > 2 116 printk(KERN_DEBUG "lapb: (%p) S%d RX %02X %02X %02X\n", 117 lapb->dev, lapb->state, 118 skb->data[0], skb->data[1], skb->data[2]); 119 #endif 120 121 /* We always need to look at 2 bytes, sometimes we need 122 * to look at 3 and those cases are handled below. 123 */ 124 if (!pskb_may_pull(skb, 2)) 125 return -1; 126 127 if (lapb->mode & LAPB_MLP) { 128 if (lapb->mode & LAPB_DCE) { 129 if (skb->data[0] == LAPB_ADDR_D) 130 frame->cr = LAPB_COMMAND; 131 if (skb->data[0] == LAPB_ADDR_C) 132 frame->cr = LAPB_RESPONSE; 133 } else { 134 if (skb->data[0] == LAPB_ADDR_C) 135 frame->cr = LAPB_COMMAND; 136 if (skb->data[0] == LAPB_ADDR_D) 137 frame->cr = LAPB_RESPONSE; 138 } 139 } else { 140 if (lapb->mode & LAPB_DCE) { 141 if (skb->data[0] == LAPB_ADDR_B) 142 frame->cr = LAPB_COMMAND; 143 if (skb->data[0] == LAPB_ADDR_A) 144 frame->cr = LAPB_RESPONSE; 145 } else { 146 if (skb->data[0] == LAPB_ADDR_A) 147 frame->cr = LAPB_COMMAND; 148 if (skb->data[0] == LAPB_ADDR_B) 149 frame->cr = LAPB_RESPONSE; 150 } 151 } 152 153 skb_pull(skb, 1); 154 155 if (lapb->mode & LAPB_EXTENDED) { 156 if (!(skb->data[0] & LAPB_S)) { 157 if (!pskb_may_pull(skb, 2)) 158 return -1; 159 /* 160 * I frame - carries NR/NS/PF 161 */ 162 frame->type = LAPB_I; 163 frame->ns = (skb->data[0] >> 1) & 0x7F; 164 frame->nr = (skb->data[1] >> 1) & 0x7F; 165 frame->pf = skb->data[1] & LAPB_EPF; 166 frame->control[0] = skb->data[0]; 167 frame->control[1] = skb->data[1]; 168 skb_pull(skb, 2); 169 } else if ((skb->data[0] & LAPB_U) == 1) { 170 if (!pskb_may_pull(skb, 2)) 171 return -1; 172 /* 173 * S frame - take out PF/NR 174 */ 175 frame->type = skb->data[0] & 0x0F; 176 frame->nr = (skb->data[1] >> 1) & 0x7F; 177 frame->pf = skb->data[1] & LAPB_EPF; 178 frame->control[0] = skb->data[0]; 179 frame->control[1] = skb->data[1]; 180 skb_pull(skb, 2); 181 } else if ((skb->data[0] & LAPB_U) == 3) { 182 /* 183 * U frame - take out PF 184 */ 185 frame->type = skb->data[0] & ~LAPB_SPF; 186 frame->pf = skb->data[0] & LAPB_SPF; 187 frame->control[0] = skb->data[0]; 188 frame->control[1] = 0x00; 189 skb_pull(skb, 1); 190 } 191 } else { 192 if (!(skb->data[0] & LAPB_S)) { 193 /* 194 * I frame - carries NR/NS/PF 195 */ 196 frame->type = LAPB_I; 197 frame->ns = (skb->data[0] >> 1) & 0x07; 198 frame->nr = (skb->data[0] >> 5) & 0x07; 199 frame->pf = skb->data[0] & LAPB_SPF; 200 } else if ((skb->data[0] & LAPB_U) == 1) { 201 /* 202 * S frame - take out PF/NR 203 */ 204 frame->type = skb->data[0] & 0x0F; 205 frame->nr = (skb->data[0] >> 5) & 0x07; 206 frame->pf = skb->data[0] & LAPB_SPF; 207 } else if ((skb->data[0] & LAPB_U) == 3) { 208 /* 209 * U frame - take out PF 210 */ 211 frame->type = skb->data[0] & ~LAPB_SPF; 212 frame->pf = skb->data[0] & LAPB_SPF; 213 } 214 215 frame->control[0] = skb->data[0]; 216 217 skb_pull(skb, 1); 218 } 219 220 return 0; 221 } 222 223 /* 224 * This routine is called when the HDLC layer internally generates a 225 * command or response for the remote machine ( eg. RR, UA etc. ). 226 * Only supervisory or unnumbered frames are processed, FRMRs are handled 227 * by lapb_transmit_frmr below. 228 */ 229 void lapb_send_control(struct lapb_cb *lapb, int frametype, 230 int poll_bit, int type) 231 { 232 struct sk_buff *skb; 233 unsigned char *dptr; 234 235 if ((skb = alloc_skb(LAPB_HEADER_LEN + 3, GFP_ATOMIC)) == NULL) 236 return; 237 238 skb_reserve(skb, LAPB_HEADER_LEN + 1); 239 240 if (lapb->mode & LAPB_EXTENDED) { 241 if ((frametype & LAPB_U) == LAPB_U) { 242 dptr = skb_put(skb, 1); 243 *dptr = frametype; 244 *dptr |= poll_bit ? LAPB_SPF : 0; 245 } else { 246 dptr = skb_put(skb, 2); 247 dptr[0] = frametype; 248 dptr[1] = (lapb->vr << 1); 249 dptr[1] |= poll_bit ? LAPB_EPF : 0; 250 } 251 } else { 252 dptr = skb_put(skb, 1); 253 *dptr = frametype; 254 *dptr |= poll_bit ? LAPB_SPF : 0; 255 if ((frametype & LAPB_U) == LAPB_S) /* S frames carry NR */ 256 *dptr |= (lapb->vr << 5); 257 } 258 259 lapb_transmit_buffer(lapb, skb, type); 260 } 261 262 /* 263 * This routine generates FRMRs based on information previously stored in 264 * the LAPB control block. 265 */ 266 void lapb_transmit_frmr(struct lapb_cb *lapb) 267 { 268 struct sk_buff *skb; 269 unsigned char *dptr; 270 271 if ((skb = alloc_skb(LAPB_HEADER_LEN + 7, GFP_ATOMIC)) == NULL) 272 return; 273 274 skb_reserve(skb, LAPB_HEADER_LEN + 1); 275 276 if (lapb->mode & LAPB_EXTENDED) { 277 dptr = skb_put(skb, 6); 278 *dptr++ = LAPB_FRMR; 279 *dptr++ = lapb->frmr_data.control[0]; 280 *dptr++ = lapb->frmr_data.control[1]; 281 *dptr++ = (lapb->vs << 1) & 0xFE; 282 *dptr = (lapb->vr << 1) & 0xFE; 283 if (lapb->frmr_data.cr == LAPB_RESPONSE) 284 *dptr |= 0x01; 285 dptr++; 286 *dptr++ = lapb->frmr_type; 287 288 #if LAPB_DEBUG > 1 289 printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X %02X %02X\n", 290 lapb->dev, lapb->state, 291 skb->data[1], skb->data[2], skb->data[3], 292 skb->data[4], skb->data[5]); 293 #endif 294 } else { 295 dptr = skb_put(skb, 4); 296 *dptr++ = LAPB_FRMR; 297 *dptr++ = lapb->frmr_data.control[0]; 298 *dptr = (lapb->vs << 1) & 0x0E; 299 *dptr |= (lapb->vr << 5) & 0xE0; 300 if (lapb->frmr_data.cr == LAPB_RESPONSE) 301 *dptr |= 0x10; 302 dptr++; 303 *dptr++ = lapb->frmr_type; 304 305 #if LAPB_DEBUG > 1 306 printk(KERN_DEBUG "lapb: (%p) S%d TX FRMR %02X %02X %02X\n", 307 lapb->dev, lapb->state, skb->data[1], 308 skb->data[2], skb->data[3]); 309 #endif 310 } 311 312 lapb_transmit_buffer(lapb, skb, LAPB_RESPONSE); 313 } 314